2 * This file is part of the Nice GLib ICE library.
4 * (C) 2006-2008 Collabora Ltd.
5 * Contact: Dafydd Harries
6 * Contact: Olivier Crete
7 * (C) 2006, 2007 Nokia Corporation. All rights reserved.
8 * Contact: Kai Vehmanen
10 * The contents of this file are subject to the Mozilla Public License Version
11 * 1.1 (the "License"); you may not use this file except in compliance with
12 * the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS" basis,
16 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 * for the specific language governing rights and limitations under the
20 * The Original Code is the Nice GLib ICE library.
22 * The Initial Developers of the Original Code are Collabora Ltd and Nokia
23 * Corporation. All Rights Reserved.
26 * Dafydd Harries, Collabora Ltd.
27 * Olivier Crete, Collabora Ltd.
28 * RĂ©mi Denis-Courmont, Nokia
31 * Alternatively, the contents of this file may be used under the terms of the
32 * the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
33 * case the provisions of LGPL are applicable instead of those above. If you
34 * wish to allow use of your version of this file only under the terms of the
35 * LGPL and not to allow others to use your version of this file under the
36 * MPL, indicate your decision by deleting the provisions above and replace
37 * them with the notice and other provisions required by the LGPL. If you do
38 * not delete the provisions above, a recipient may use your version of this
39 * file under either the MPL or the LGPL.
43 * Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
44 * http://en.wikipedia.org/wiki/Berkeley_sockets.)
50 #include "pseudossl.h"
60 NiceSocket
*base_socket
;
72 static const gchar SSL_SERVER_HANDSHAKE
[] = {
73 0x16, 0x03, 0x01, 0x00, 0x4a, 0x02, 0x00, 0x00,
74 0x46, 0x03, 0x01, 0x42, 0x85, 0x45, 0xa7, 0x27,
75 0xa9, 0x5d, 0xa0, 0xb3, 0xc5, 0xe7, 0x53, 0xda,
76 0x48, 0x2b, 0x3f, 0xc6, 0x5a, 0xca, 0x89, 0xc1,
77 0x58, 0x52, 0xa1, 0x78, 0x3c, 0x5b, 0x17, 0x46,
78 0x00, 0x85, 0x3f, 0x20, 0x0e, 0xd3, 0x06, 0x72,
79 0x5b, 0x5b, 0x1b, 0x5f, 0x15, 0xac, 0x13, 0xf9,
80 0x88, 0x53, 0x9d, 0x9b, 0xe8, 0x3d, 0x7b, 0x0c,
81 0x30, 0x32, 0x6e, 0x38, 0x4d, 0xa2, 0x75, 0x57,
82 0x41, 0x6c, 0x34, 0x5c, 0x00, 0x04, 0x00};
84 static const gchar SSL_CLIENT_HANDSHAKE
[] = {
85 0x80, 0x46, 0x01, 0x03, 0x01, 0x00, 0x2d, 0x00,
86 0x00, 0x00, 0x10, 0x01, 0x00, 0x80, 0x03, 0x00,
87 0x80, 0x07, 0x00, 0xc0, 0x06, 0x00, 0x40, 0x02,
88 0x00, 0x80, 0x04, 0x00, 0x80, 0x00, 0x00, 0x04,
89 0x00, 0xfe, 0xff, 0x00, 0x00, 0x0a, 0x00, 0xfe,
90 0xfe, 0x00, 0x00, 0x09, 0x00, 0x00, 0x64, 0x00,
91 0x00, 0x62, 0x00, 0x00, 0x03, 0x00, 0x00, 0x06,
92 0x1f, 0x17, 0x0c, 0xa6, 0x2f, 0x00, 0x78, 0xfc,
93 0x46, 0x55, 0x2e, 0xb1, 0x83, 0x39, 0xf1, 0xea};
96 static void socket_close (NiceSocket
*sock
);
97 static gint
socket_recv (NiceSocket
*sock
, NiceAddress
*from
,
98 guint len
, gchar
*buf
);
99 static gboolean
socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
100 guint len
, const gchar
*buf
);
101 static gboolean
socket_is_reliable (NiceSocket
*sock
);
103 static void add_to_be_sent (NiceSocket
*sock
, const NiceAddress
*to
,
104 const gchar
*buf
, guint len
);
105 static void free_to_be_sent (struct to_be_sent
*tbs
);
109 nice_pseudossl_socket_new (NiceAgent
*agent
, NiceSocket
*base_socket
)
112 NiceSocket
*sock
= g_slice_new0 (NiceSocket
);
113 sock
->priv
= priv
= g_slice_new0 (PseudoSSLPriv
);
115 priv
->handshaken
= FALSE
;
116 priv
->base_socket
= base_socket
;
118 sock
->fileno
= priv
->base_socket
->fileno
;
119 sock
->addr
= priv
->base_socket
->addr
;
120 sock
->send
= socket_send
;
121 sock
->recv
= socket_recv
;
122 sock
->is_reliable
= socket_is_reliable
;
123 sock
->close
= socket_close
;
125 /* We send 'to' NULL because it will always be to an already connected
126 * TCP base socket, which ignores the destination */
127 nice_socket_send (priv
->base_socket
, NULL
,
128 sizeof(SSL_CLIENT_HANDSHAKE
), SSL_CLIENT_HANDSHAKE
);
135 socket_close (NiceSocket
*sock
)
137 PseudoSSLPriv
*priv
= sock
->priv
;
139 if (priv
->base_socket
)
140 nice_socket_free (priv
->base_socket
);
142 g_queue_foreach (&priv
->send_queue
, (GFunc
) free_to_be_sent
, NULL
);
143 g_queue_clear (&priv
->send_queue
);
145 g_slice_free(PseudoSSLPriv
, sock
->priv
);
150 socket_recv (NiceSocket
*sock
, NiceAddress
*from
, guint len
, gchar
*buf
)
152 PseudoSSLPriv
*priv
= sock
->priv
;
154 if (priv
->handshaken
) {
155 if (priv
->base_socket
)
156 return nice_socket_recv (priv
->base_socket
, from
, len
, buf
);
158 gchar data
[sizeof(SSL_SERVER_HANDSHAKE
)];
161 if (priv
->base_socket
)
162 ret
= nice_socket_recv (priv
->base_socket
, from
, sizeof(data
), data
);
166 } else if ((guint
) ret
== sizeof(SSL_SERVER_HANDSHAKE
) &&
167 memcmp(SSL_SERVER_HANDSHAKE
, data
, sizeof(SSL_SERVER_HANDSHAKE
)) == 0) {
168 struct to_be_sent
*tbs
= NULL
;
169 priv
->handshaken
= TRUE
;
170 while ((tbs
= g_queue_pop_head (&priv
->send_queue
))) {
171 nice_socket_send (priv
->base_socket
, &tbs
->to
, tbs
->length
, tbs
->buf
);
173 g_slice_free (struct to_be_sent
, tbs
);
176 if (priv
->base_socket
)
177 nice_socket_free (priv
->base_socket
);
178 priv
->base_socket
= NULL
;
187 socket_send (NiceSocket
*sock
, const NiceAddress
*to
,
188 guint len
, const gchar
*buf
)
190 PseudoSSLPriv
*priv
= sock
->priv
;
192 if (priv
->handshaken
) {
193 if (priv
->base_socket
)
194 return nice_socket_send (priv
->base_socket
, to
, len
, buf
);
198 add_to_be_sent (sock
, to
, buf
, len
);
205 socket_is_reliable (NiceSocket
*sock
)
212 add_to_be_sent (NiceSocket
*sock
, const NiceAddress
*to
,
213 const gchar
*buf
, guint len
)
215 PseudoSSLPriv
*priv
= sock
->priv
;
216 struct to_be_sent
*tbs
= NULL
;
221 tbs
= g_slice_new0 (struct to_be_sent
);
222 tbs
->buf
= g_memdup (buf
, len
);
226 g_queue_push_tail (&priv
->send_queue
, tbs
);
231 free_to_be_sent (struct to_be_sent
*tbs
)
234 g_slice_free (struct to_be_sent
, tbs
);