2009-06-12 Bill Holmes <billholmes54@gmail.com>
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / TcpChannelListener.cs
1 // 
2 // TcpChannelListener.cs
3 // 
4 // Author: 
5 //     Marcos Cobena (marcoscobena@gmail.com)
6 // 
7 // Copyright 2007 Marcos Cobena (http://www.youcannoteatbits.org/)
8 // 
9
10 using System;
11 using System.Collections.Generic;
12 using System.IO;
13 using System.Net;
14 using System.Net.Sockets;
15 using System.ServiceModel.Description;
16 using System.Text;
17 using System.Xml;
18
19 namespace System.ServiceModel.Channels
20 {
21         internal class TcpChannelListener<TChannel> : InternalChannelListenerBase<TChannel> 
22                 where TChannel : class, IChannel
23         {
24                 List<IChannel> channels = new List<IChannel> ();
25                 BindingContext context;
26                 TcpChannelInfo info;
27                 IDuplexSession session;
28                 Uri listen_uri;
29                 TcpListener tcp_listener;
30                 
31                 [MonoTODO]
32                 public TcpChannelListener (TcpTransportBindingElement source, 
33                                            BindingContext context) : base (context.Binding)
34                 {
35                         MessageEncoder encoder = null;
36                         XmlDictionaryReaderQuotas quotas = null;
37
38                         if (context.ListenUriMode == ListenUriMode.Explicit)
39                                 listen_uri =
40                                         context.ListenUriRelativeAddress != null ?
41                                         new Uri (context.ListenUriBaseAddress, context.ListenUriRelativeAddress) :
42                                         context.ListenUriBaseAddress;
43                         else
44                                 throw new NotImplementedException ();
45                         
46                         foreach (BindingElement be in context.RemainingBindingElements) {
47                                 MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
48                                 if (mbe != null) {
49                                         encoder = CreateEncoder<TChannel> (mbe);
50                                         quotas = mbe.GetProperty<XmlDictionaryReaderQuotas> (context);
51                                         break;
52                                 }
53                         }
54                         
55                         if (encoder == null)
56                                 encoder = new BinaryMessageEncoder ();
57
58                         info = new TcpChannelInfo (source, encoder, quotas);
59                 }
60                 
61                 public override Uri Uri {
62                         get { return listen_uri; }
63                 }
64                 
65                 [MonoTODO]
66                 protected override TChannel OnAcceptChannel (TimeSpan timeout)
67                 {
68                         TChannel channel = PopulateChannel (timeout);
69                         channels.Add (channel);
70                         return channel;
71                 }
72                 
73                 TChannel PopulateChannel (TimeSpan timeout)
74                 {
75                         // FIXME: pass delegate or something to remove the channel instance from "channels" when it is closed.
76                         if (typeof (TChannel) == typeof (IDuplexSessionChannel))
77                                 return (TChannel) (object) new TcpDuplexSessionChannel (this, info, tcp_listener, timeout);
78
79                         // FIXME: To implement more.
80                         throw new NotImplementedException ();
81                 }
82
83                 [MonoTODO]
84                 protected override bool OnWaitForChannel (TimeSpan timeout)
85                 {
86                         throw new NotImplementedException ();
87                 }
88                 
89                 // CommunicationObject
90                 
91                 protected override void OnAbort ()
92                 {
93                         if (State == CommunicationState.Closed)
94                                 return;
95                         ProcessClose ();
96                 }
97
98                 protected override void OnClose (TimeSpan timeout)
99                 {
100                         if (State == CommunicationState.Closed)
101                                 return;
102                         ProcessClose ();
103                 }
104
105                 void ProcessClose ()
106                 {
107                         if (tcp_listener == null)
108                                 throw new InvalidOperationException ("Current state is " + State);
109                         tcp_listener.Stop ();
110                         tcp_listener = null;
111                 }
112
113                 [MonoTODO]
114                 protected override void OnOpen (TimeSpan timeout)
115                 {
116                         IPHostEntry entry = Dns.GetHostEntry (listen_uri.Host);
117                         
118                         if (entry.AddressList.Length ==0)
119                                 throw new ArgumentException (String.Format ("Invalid listen URI: {0}", listen_uri));
120                         
121                         int explicitPort = listen_uri.Port;
122                         tcp_listener = new TcpListener (entry.AddressList [0], explicitPort <= 0 ? TcpTransportBindingElement.DefaultPort : explicitPort);
123                         tcp_listener.Start ();
124                 }
125         }
126 }