blob: 948b1d7c654b3fd6bf89f0fd572f03d32d5c16e9 [file] [log] [blame]
Jens Geyerc1d79432014-04-22 22:52:43 +02001/**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20using System;
21using System.Net.Sockets;
22using System.Security.Cryptography.X509Certificates;
23
24namespace Thrift.Transport
25{
26 /// <summary>
27 /// SSL Server Socket Wrapper Class
28 /// </summary>
29 public class TTLSServerSocket : TServerTransport
30 {
31 /// <summary>
32 /// Underlying tcp server
33 /// </summary>
34 private TcpListener server = null;
35
36 /// <summary>
37 /// The port where the socket listen
38 /// </summary>
39 private int port = 0;
40
41 /// <summary>
42 /// Timeout for the created server socket
43 /// </summary>
44 private int clientTimeout = 0;
45
46 /// <summary>
47 /// Whether or not to wrap new TSocket connections in buffers
48 /// </summary>
49 private bool useBufferedSockets = false;
50
51 /// <summary>
52 /// The servercertificate with the private- and public-key
53 /// </summary>
54 private X509Certificate serverCertificate;
55
56
57 /// <summary>
58 /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
59 /// </summary>
60 /// <param name="port">The port where the server runs.</param>
61 /// <param name="certificate">The certificate object.</param>
62 public TTLSServerSocket(int port, X509Certificate2 certificate)
63 : this(port, 0, certificate)
64 {
65 }
66
67 /// <summary>
68 /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
69 /// </summary>
70 /// <param name="port">The port where the server runs.</param>
71 /// <param name="clientTimeout">Send/receive timeout.</param>
72 /// <param name="certificate">The certificate object.</param>
73 public TTLSServerSocket(int port, int clientTimeout, X509Certificate2 certificate)
74 : this(port, clientTimeout, false, certificate)
75 {
76 }
77
78 /// <summary>
79 /// Initializes a new instance of the <see cref="TTLSServerSocket" /> class.
80 /// </summary>
81 /// <param name="port">The port where the server runs.</param>
82 /// <param name="clientTimeout">Send/receive timeout.</param>
83 /// <param name="useBufferedSockets">If set to <c>true</c> [use buffered sockets].</param>
84 /// <param name="certificate">The certificate object.</param>
85 public TTLSServerSocket(int port, int clientTimeout, bool useBufferedSockets, X509Certificate2 certificate)
86 {
87 if (!certificate.HasPrivateKey)
88 {
89 throw new TTransportException(TTransportException.ExceptionType.Unknown, "Your server-certificate needs to have a private key");
90 }
91
92 this.port = port;
93 this.serverCertificate = certificate;
94 this.useBufferedSockets = useBufferedSockets;
95 try
96 {
97 // Create server socket
98 server = new TcpListener(System.Net.IPAddress.Any, this.port);
99 server.Server.NoDelay = true;
100 }
101 catch (Exception)
102 {
103 server = null;
104 throw new TTransportException("Could not create ServerSocket on port " + port + ".");
105 }
106 }
107
108 /// <summary>
109 /// Starts the server.
110 /// </summary>
111 public override void Listen()
112 {
113 // Make sure accept is not blocking
114 if (this.server != null)
115 {
116 try
117 {
118 this.server.Start();
119 }
120 catch (SocketException sx)
121 {
122 throw new TTransportException("Could not accept on listening socket: " + sx.Message);
123 }
124 }
125 }
126
127 /// <summary>
128 /// Callback for Accept Implementation
129 /// </summary>
130 /// <returns>
131 /// TTransport-object.
132 /// </returns>
133 protected override TTransport AcceptImpl()
134 {
135 if (this.server == null)
136 {
137 throw new TTransportException(TTransportException.ExceptionType.NotOpen, "No underlying server socket.");
138 }
139
140 try
141 {
142 TcpClient client = this.server.AcceptTcpClient();
143 client.SendTimeout = client.ReceiveTimeout = this.clientTimeout;
144
145 //wrap the client in an SSL Socket passing in the SSL cert
146 TTLSSocket socket = new TTLSSocket(client, this.serverCertificate, true);
147
148 socket.setupTLS();
149
150 if (useBufferedSockets)
151 {
152 TBufferedTransport trans = new TBufferedTransport(socket);
153 return trans;
154 }
155 else
156 {
157 return socket;
158 }
159
160 }
161 catch (Exception ex)
162 {
163 throw new TTransportException(ex.ToString());
164 }
165 }
166
167 /// <summary>
168 /// Stops the Server
169 /// </summary>
170 public override void Close()
171 {
172 if (this.server != null)
173 {
174 try
175 {
176 this.server.Stop();
177 }
178 catch (Exception ex)
179 {
180 throw new TTransportException("WARNING: Could not close server socket: " + ex);
181 }
182 this.server = null;
183 }
184 }
185 }
186}