2 * This file is part of the Nice GLib ICE library.
4 * (C) 2008-2009 Collabora Ltd.
5 * Contact: Youness Alaoui
6 * (C) 2008-2009 Nokia Corporation. All rights reserved.
8 * The contents of this file are subject to the Mozilla Public License Version
9 * 1.1 (the "License"); you may not use this file except in compliance with
10 * the License. You may obtain a copy of the License at
11 * http://www.mozilla.org/MPL/
13 * Software distributed under the License is distributed on an "AS IS" basis,
14 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 * for the specific language governing rights and limitations under the
18 * The Original Code is the Nice GLib ICE library.
20 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
21 * Corporation. All Rights Reserved.
24 * Youness Alaoui, Collabora Ltd.
26 * Alternatively, the contents of this file may be used under the terms of the
27 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
28 * case the provisions of LGPL are applicable instead of those above. If you
29 * wish to allow use of your version of this file only under the terms of the
30 * LGPL and not to allow others to use your version of this file under the
31 * MPL, indicate your decision by deleting the provisions above and replace
32 * them with the notice and other provisions required by the LGPL. If you do
33 * not delete the provisions above, a recipient may use your version of this
34 * file under either the MPL or the LGPL.
38 * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
39 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
45 #include "pseudossl.h"
55 NiceSocket
*base_socket
;
67 static const gchar SSL_SERVER_HANDSHAKE
[] = {
68 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
69 0x46, 0x03, 0x01, 0x42, 0x85, 0x45, 0xa7, 0x27,
70 0xa9, 0x5d, 0xa0, 0xb3, 0xc5, 0xe7, 0x53, 0xda,
71 0x48, 0x2b, 0x3f, 0xc6, 0x5a, 0xca, 0x89, 0xc1,
72 0x58, 0x52, 0xa1, 0x78, 0x3c, 0x5b, 0x17, 0x46,
73 0x00, 0x85, 0x3f, 0x20, 0x0e, 0xd3, 0x06, 0x72,
74 0x5b, 0x5b, 0x1b, 0x5f, 0x15, 0xac, 0x13, 0xf9,
75 0x88, 0x53, 0x9d, 0x9b, 0xe8, 0x3d, 0x7b, 0x0c,
76 0x30, 0x32, 0x6e, 0x38, 0x4d, 0xa2, 0x75, 0x57,
77 0x41, 0x6c, 0x34, 0x5c, 0x00, 0x04, 0x00};
79 static const gchar SSL_CLIENT_HANDSHAKE
[] = {
80 0x80, 0x46, 0x01, 0x03, 0x01, 0x00, 0x2d, 0x00,
81 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x03, 0x00,
82 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x40, 0x02,
83 0x00, 0x80, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04,
84 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, 0x00, 0xfe,
85 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, 0x00,
86 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06,
87 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc,
88 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea};
91 static void socket_close (NiceSocket
*sock
);
92 static gint
socket_recv (NiceSocket
*sock
, NiceAddress
*from
,
93 guint len
, gchar
*buf
);
94 static gboolean
socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
95 guint len
, const gchar
*buf
);
96 static gboolean
socket_is_reliable (NiceSocket
*sock
);
98 static void add_to_be_sent (NiceSocket
*sock
, const NiceAddress
*to
,
99 const gchar
*buf
, guint len
);
100 static void free_to_be_sent (struct to_be_sent
*tbs
);
104 nice_pseudossl_socket_new (NiceAgent
*agent
, NiceSocket
*base_socket
)
107 NiceSocket
*sock
= g_slice_new0 (NiceSocket
);
108 sock
->priv
= priv
= g_slice_new0 (PseudoSSLPriv
);
110 priv
->handshaken
= FALSE
;
111 priv
->base_socket
= base_socket
;
113 sock
->fileno
= priv
->base_socket
->fileno
;
114 sock
->addr
= priv
->base_socket
->addr
;
115 sock
->send
= socket_send
;
116 sock
->recv
= socket_recv
;
117 sock
->is_reliable
= socket_is_reliable
;
118 sock
->close
= socket_close
;
120 /* We send 'to' NULL because it will always be to an already connected
121 * TCP base socket, which ignores the destination */
122 nice_socket_send (priv
->base_socket
, NULL
,
123 sizeof(SSL_CLIENT_HANDSHAKE
), SSL_CLIENT_HANDSHAKE
);
130 socket_close (NiceSocket
*sock
)
132 PseudoSSLPriv
*priv
= sock
->priv
;
134 if (priv
->base_socket
)
135 nice_socket_free (priv
->base_socket
);
137 g_queue_foreach (&priv
->send_queue
, (GFunc
) free_to_be_sent
, NULL
);
138 g_queue_clear (&priv
->send_queue
);
140 g_slice_free(PseudoSSLPriv
, sock
->priv
);
145 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
147 PseudoSSLPriv
*priv
= sock
->priv
;
149 if (priv
->handshaken
) {
150 if (priv
->base_socket
)
151 return nice_socket_recv (priv
->base_socket
, from
, len
, buf
);
153 gchar data
[sizeof(SSL_SERVER_HANDSHAKE
)];
156 if (priv
->base_socket
)
157 ret
= nice_socket_recv (priv
->base_socket
, from
, sizeof(data
), data
);
161 } else if ((guint
) ret
== sizeof(SSL_SERVER_HANDSHAKE
) &&
162 memcmp(SSL_SERVER_HANDSHAKE
, data
, sizeof(SSL_SERVER_HANDSHAKE
)) == 0) {
163 struct to_be_sent
*tbs
= NULL
;
164 priv
->handshaken
= TRUE
;
165 while ((tbs
= g_queue_pop_head (&priv
->send_queue
))) {
166 nice_socket_send (priv
->base_socket
, &tbs
->to
, tbs
->length
, tbs
->buf
);
168 g_slice_free (struct to_be_sent
, tbs
);
171 if (priv
->base_socket
)
172 nice_socket_free (priv
->base_socket
);
173 priv
->base_socket
= NULL
;
182 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
183 guint len
, const gchar
*buf
)
185 PseudoSSLPriv
*priv
= sock
->priv
;
187 if (priv
->handshaken
) {
188 if (priv
->base_socket
)
189 return nice_socket_send (priv
->base_socket
, to
, len
, buf
);
193 add_to_be_sent (sock
, to
, buf
, len
);
200 socket_is_reliable (NiceSocket
*sock
)
207 add_to_be_sent (NiceSocket
*sock
, const NiceAddress
*to
,
208 const gchar
*buf
, guint len
)
210 PseudoSSLPriv
*priv
= sock
->priv
;
211 struct to_be_sent
*tbs
= NULL
;
216 tbs
= g_slice_new0 (struct to_be_sent
);
217 tbs
->buf
= g_memdup (buf
, len
);
221 g_queue_push_tail (&priv
->send_queue
, tbs
);
226 free_to_be_sent (struct to_be_sent
*tbs
)
229 g_slice_free (struct to_be_sent
, tbs
);