Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
libnice
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
libnice
Commits
b21caf2e
Commit
b21caf2e
authored
Dec 19, 2008
by
Youness Alaoui
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding HTTP proxy support
parent
16d1a06d
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
481 additions
and
8 deletions
+481
-8
agent/agent.c
agent/agent.c
+12
-8
socket/Makefile.am
socket/Makefile.am
+2
-0
socket/http.c
socket/http.c
+411
-0
socket/http.h
socket/http.h
+55
-0
socket/socket.h
socket/socket.h
+1
-0
No files found.
agent/agent.c
View file @
b21caf2e
...
...
@@ -918,15 +918,19 @@ priv_add_new_candidate_discovery_turn (NiceAgent *agent,
nice_address_set_port
(
&
proxy_server
,
agent
->
proxy_port
);
socket
=
nice_tcp_bsd_socket_new
(
agent
,
component
->
ctx
,
&
proxy_server
);
if
(
socket
&&
agent
->
proxy_type
==
NICE_PROXY_TYPE_SOCKS5
)
{
if
(
socket
)
{
if
(
agent
->
proxy_type
==
NICE_PROXY_TYPE_SOCKS5
)
{
socket
=
nice_socks5_socket_new
(
socket
,
&
turn
->
server
,
agent
->
proxy_username
,
agent
->
proxy_password
);
}
else
if
(
agent
->
proxy_type
==
NICE_PROXY_TYPE_HTTP
){
socket
=
nice_http_socket_new
(
socket
,
&
turn
->
server
,
agent
->
proxy_username
,
agent
->
proxy_password
);
}
else
{
/* TODO add HTTP support */
nice_socket_free
(
socket
);
socket
=
NULL
;
}
}
}
if
(
socket
==
NULL
)
{
...
...
socket/Makefile.am
View file @
b21caf2e
...
...
@@ -30,6 +30,8 @@ libsocket_la_SOURCES = \
pseudossl.c
\
socks5.h
\
socks5.c
\
http.h
\
http.c
\
turn.h
\
turn.c
\
tcp-turn.h
\
...
...
socket/http.c
0 → 100644
View file @
b21caf2e
/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2008 Collabora Ltd.
* Contact: Youness Alaoui
* (C) 2008 Nokia Corporation. All rights reserved.
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
* Contributors:
* Youness Alaoui, Collabora Ltd.
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
/*
* Implementation of TCP relay socket interface using TCP Berkeley sockets. (See
* http://en.wikipedia.org/wiki/Berkeley_sockets.)
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "http.h"
#include <string.h>
#include <stdlib.h>
#ifndef G_OS_WIN32
#include <unistd.h>
#endif
#define HTTP_USER_AGENT "libnice"
typedef
enum
{
HTTP_STATE_INIT
,
HTTP_STATE_HEADERS
,
HTTP_STATE_BODY
,
HTTP_STATE_CONNECTED
,
HTTP_STATE_ERROR
}
HttpState
;
typedef
struct
{
HttpState
state
;
NiceSocket
*
base_socket
;
NiceAddress
addr
;
gchar
*
username
;
gchar
*
password
;
GQueue
send_queue
;
gchar
*
recv_buf
;
gint
recv_len
;
gint
content_length
;
}
HttpPriv
;
struct
to_be_sent
{
guint
length
;
gchar
*
buf
;
NiceAddress
to
;
};
static
void
socket_close
(
NiceSocket
*
sock
);
static
gint
socket_recv
(
NiceSocket
*
sock
,
NiceAddress
*
from
,
guint
len
,
gchar
*
buf
);
static
gboolean
socket_send
(
NiceSocket
*
sock
,
const
NiceAddress
*
to
,
guint
len
,
const
gchar
*
buf
);
static
gboolean
socket_is_reliable
(
NiceSocket
*
sock
);
static
void
add_to_be_sent
(
NiceSocket
*
sock
,
const
NiceAddress
*
to
,
const
gchar
*
buf
,
guint
len
);
static
void
free_to_be_sent
(
struct
to_be_sent
*
tbs
);
NiceSocket
*
nice_http_socket_new
(
NiceSocket
*
base_socket
,
NiceAddress
*
addr
,
gchar
*
username
,
gchar
*
password
)
{
HttpPriv
*
priv
;
NiceSocket
*
sock
=
NULL
;
if
(
addr
)
{
sock
=
g_slice_new0
(
NiceSocket
);
sock
->
priv
=
priv
=
g_slice_new0
(
HttpPriv
);
priv
->
base_socket
=
base_socket
;
priv
->
addr
=
*
addr
;
priv
->
username
=
g_strdup
(
username
);
priv
->
password
=
g_strdup
(
password
);
priv
->
recv_buf
=
NULL
;
priv
->
recv_len
=
0
;
priv
->
content_length
=
0
;
sock
->
fileno
=
priv
->
base_socket
->
fileno
;
sock
->
addr
=
priv
->
base_socket
->
addr
;
sock
->
send
=
socket_send
;
sock
->
recv
=
socket_recv
;
sock
->
is_reliable
=
socket_is_reliable
;
sock
->
close
=
socket_close
;
/* Send HTTP CONNECT */
{
gchar
*
msg
=
NULL
;
gchar
*
credential
=
NULL
;
gchar
host
[
INET6_ADDRSTRLEN
];
gint
port
=
nice_address_get_port
(
&
priv
->
addr
);
nice_address_to_string
(
&
priv
->
addr
,
host
);
if
(
username
)
{
gchar
*
userpass
=
g_strdup_printf
(
"%s:%s"
,
username
,
password
?
password
:
""
);
gchar
*
auth
=
g_base64_encode
((
guchar
*
)
userpass
,
strlen
(
userpass
));
credential
=
g_strdup_printf
(
"Proxy-Authorization: Basic %s
\r\n
"
,
auth
);
g_free
(
auth
);
g_free
(
userpass
);
}
msg
=
g_strdup_printf
(
"CONNECT %s:%d HTTP/1.0
\r\n
"
"Host: %s
\r\n
"
"User-Agent: %s
\r\n
"
"Content-Length: 0
\r\n
"
"Proxy-Connection: Keep-Alive
\r\n
"
"Connection: Keep-Alive
\r\n
"
"Cache-Control: no-cache
\r\n
"
"Pragma: no-cache
\r\n
"
"%s
\r\n
"
,
host
,
port
,
host
,
HTTP_USER_AGENT
,
credential
?
credential
:
""
);
g_free
(
credential
);
nice_socket_send
(
priv
->
base_socket
,
NULL
,
strlen
(
msg
),
msg
);
priv
->
state
=
HTTP_STATE_INIT
;
g_free
(
msg
);
}
}
return
sock
;
}
static
void
socket_close
(
NiceSocket
*
sock
)
{
HttpPriv
*
priv
=
sock
->
priv
;
if
(
priv
->
base_socket
)
nice_socket_free
(
priv
->
base_socket
);
if
(
priv
->
username
)
g_free
(
priv
->
username
);
if
(
priv
->
password
)
g_free
(
priv
->
password
);
if
(
priv
->
recv_buf
)
g_free
(
priv
->
recv_buf
);
g_queue_foreach
(
&
priv
->
send_queue
,
(
GFunc
)
free_to_be_sent
,
NULL
);
g_queue_clear
(
&
priv
->
send_queue
);
g_slice_free
(
HttpPriv
,
sock
->
priv
);
}
static
gint
socket_recv
(
NiceSocket
*
sock
,
NiceAddress
*
from
,
guint
len
,
gchar
*
buf
)
{
HttpPriv
*
priv
=
sock
->
priv
;
gint
read
=
-
1
;
if
(
priv
->
base_socket
)
read
=
nice_socket_recv
(
priv
->
base_socket
,
from
,
len
,
buf
);
if
(
read
<=
0
||
priv
->
state
==
HTTP_STATE_CONNECTED
)
{
return
read
;
}
else
{
priv
->
recv_buf
=
g_realloc
(
priv
->
recv_buf
,
priv
->
recv_len
+
read
);
memcpy
(
priv
->
recv_buf
+
priv
->
recv_len
,
buf
,
read
);
priv
->
recv_len
+=
read
;
}
retry:
nice_debug
(
"Receiving from HTTP proxy (state %d) : %d
\n
'%s'"
,
priv
->
state
,
priv
->
recv_len
,
priv
->
recv_buf
);
switch
(
priv
->
state
)
{
case
HTTP_STATE_INIT
:
{
gint
pos
=
0
;
/* Remove any leading spaces (could happen!) */
while
(
pos
<
priv
->
recv_len
&&
priv
->
recv_buf
[
pos
]
==
' '
)
pos
++
;
/* Make sure we have enough data */
if
(
pos
>=
priv
->
recv_len
)
goto
not_enough_data
;
if
(
pos
+
7
>
priv
->
recv_len
)
goto
not_enough_data
;
if
(
strncmp
(
priv
->
recv_buf
+
pos
,
"HTTP/1."
,
7
)
!=
0
)
goto
error
;
pos
+=
7
;
if
(
pos
>=
priv
->
recv_len
)
goto
not_enough_data
;
if
(
priv
->
recv_buf
[
pos
]
!=
'0'
&&
priv
->
recv_buf
[
pos
]
!=
'1'
)
goto
error
;
pos
++
;
/* Make sure we have a space after the HTTP version */
if
(
pos
>=
priv
->
recv_len
)
goto
not_enough_data
;
if
(
priv
->
recv_buf
[
pos
]
!=
' '
)
goto
error
;
/* Skip all spaces (could be more than one!) */
while
(
pos
<
priv
->
recv_len
&&
priv
->
recv_buf
[
pos
]
==
' '
)
pos
++
;
if
(
pos
>=
priv
->
recv_len
)
goto
not_enough_data
;
/* Check for a successfull 2xx code */
if
(
pos
+
3
>
priv
->
recv_len
)
goto
not_enough_data
;
if
(
priv
->
recv_buf
[
pos
]
!=
'2'
||
priv
->
recv_buf
[
pos
+
1
]
<
'0'
||
priv
->
recv_buf
[
pos
+
1
]
>
'9'
||
priv
->
recv_buf
[
pos
+
2
]
<
'0'
||
priv
->
recv_buf
[
pos
+
2
]
>
'9'
)
goto
error
;
/* Clear any trailing chars */
while
(
pos
+
1
<
priv
->
recv_len
&&
priv
->
recv_buf
[
pos
]
!=
'\r'
&&
priv
->
recv_buf
[
pos
+
1
]
!=
'\n'
)
pos
++
;
if
(
pos
+
1
>=
priv
->
recv_len
)
goto
not_enough_data
;
pos
+=
2
;
/* consume the data we just parsed */
priv
->
recv_len
-=
pos
;
memmove
(
priv
->
recv_buf
,
priv
->
recv_buf
+
pos
,
priv
->
recv_len
);
priv
->
recv_buf
=
g_realloc
(
priv
->
recv_buf
,
priv
->
recv_len
);
priv
->
content_length
=
0
;
priv
->
state
=
HTTP_STATE_HEADERS
;
goto
retry
;
}
break
;
case
HTTP_STATE_HEADERS
:
{
gint
pos
=
0
;
if
(
pos
+
15
<
priv
->
recv_len
&&
g_ascii_strncasecmp
(
priv
->
recv_buf
,
"Content-Length:"
,
15
)
==
0
)
{
priv
->
content_length
=
atoi
(
priv
->
recv_buf
+
15
);
}
while
(
pos
+
1
<
priv
->
recv_len
&&
priv
->
recv_buf
[
pos
]
!=
'\r'
&&
priv
->
recv_buf
[
pos
+
1
]
!=
'\n'
)
pos
++
;
nice_debug
(
"pos = %d, len = %d"
,
pos
,
priv
->
recv_len
);
if
(
pos
+
1
>=
priv
->
recv_len
)
goto
not_enough_data
;
pos
+=
2
;
/* consume the data we just parsed */
priv
->
recv_len
-=
pos
;
memmove
(
priv
->
recv_buf
,
priv
->
recv_buf
+
pos
,
priv
->
recv_len
);
priv
->
recv_buf
=
g_realloc
(
priv
->
recv_buf
,
priv
->
recv_len
);
if
(
pos
==
2
)
priv
->
state
=
HTTP_STATE_BODY
;
goto
retry
;
}
break
;
case
HTTP_STATE_BODY
:
{
gint
consumed
=
priv
->
content_length
;
if
(
priv
->
content_length
==
0
)
{
priv
->
state
=
HTTP_STATE_CONNECTED
;
goto
retry
;
}
if
(
priv
->
recv_len
==
0
)
goto
not_enough_data
;
if
(
priv
->
content_length
>
priv
->
recv_len
)
consumed
=
priv
->
recv_len
;
priv
->
recv_len
-=
consumed
;
priv
->
content_length
-=
consumed
;
memmove
(
priv
->
recv_buf
,
priv
->
recv_buf
+
consumed
,
priv
->
recv_len
);
priv
->
recv_buf
=
g_realloc
(
priv
->
recv_buf
,
priv
->
recv_len
);
goto
retry
;
}
break
;
case
HTTP_STATE_CONNECTED
:
{
guint
read
=
priv
->
recv_len
;
struct
to_be_sent
*
tbs
=
NULL
;
if
(
read
>
len
)
read
=
len
;
memcpy
(
buf
,
priv
->
recv_buf
,
read
);
/* consume the data we returned */
priv
->
recv_len
-=
read
;
memmove
(
priv
->
recv_buf
,
priv
->
recv_buf
+
read
,
priv
->
recv_len
);
priv
->
recv_buf
=
g_realloc
(
priv
->
recv_buf
,
priv
->
recv_len
);
/* Send the pending data */
while
((
tbs
=
g_queue_pop_head
(
&
priv
->
send_queue
)))
{
nice_socket_send
(
priv
->
base_socket
,
&
tbs
->
to
,
tbs
->
length
,
tbs
->
buf
);
g_free
(
tbs
->
buf
);
g_slice_free
(
struct
to_be_sent
,
tbs
);
}
return
read
;
}
break
;
default:
/* Unknown status */
goto
error
;
}
not_enough_data:
return
0
;
error:
nice_debug
(
"http error"
);
if
(
priv
->
base_socket
)
nice_socket_free
(
priv
->
base_socket
);
priv
->
base_socket
=
NULL
;
priv
->
state
=
HTTP_STATE_ERROR
;
return
-
1
;
}
static
gboolean
socket_send
(
NiceSocket
*
sock
,
const
NiceAddress
*
to
,
guint
len
,
const
gchar
*
buf
)
{
HttpPriv
*
priv
=
sock
->
priv
;
if
(
priv
->
state
==
HTTP_STATE_CONNECTED
)
{
if
(
priv
->
base_socket
)
return
nice_socket_send
(
priv
->
base_socket
,
to
,
len
,
buf
);
else
return
FALSE
;
}
else
if
(
priv
->
state
==
HTTP_STATE_ERROR
)
{
return
FALSE
;
}
else
{
add_to_be_sent
(
sock
,
to
,
buf
,
len
);
}
return
TRUE
;
}
static
gboolean
socket_is_reliable
(
NiceSocket
*
sock
)
{
return
TRUE
;
}
static
void
add_to_be_sent
(
NiceSocket
*
sock
,
const
NiceAddress
*
to
,
const
gchar
*
buf
,
guint
len
)
{
HttpPriv
*
priv
=
sock
->
priv
;
struct
to_be_sent
*
tbs
=
NULL
;
if
(
len
<=
0
)
return
;
tbs
=
g_slice_new0
(
struct
to_be_sent
);
tbs
->
buf
=
g_memdup
(
buf
,
len
);
tbs
->
length
=
len
;
if
(
to
)
tbs
->
to
=
*
to
;
g_queue_push_tail
(
&
priv
->
send_queue
,
tbs
);
}
static
void
free_to_be_sent
(
struct
to_be_sent
*
tbs
)
{
g_free
(
tbs
->
buf
);
g_slice_free
(
struct
to_be_sent
,
tbs
);
}
socket/http.h
0 → 100644
View file @
b21caf2e
/*
* This file is part of the Nice GLib ICE library.
*
* (C) 2006, 2007 Collabora Ltd.
* Contact: Dafydd Harries
* (C) 2006, 2007 Nokia Corporation. All rights reserved.
* Contact: Kai Vehmanen
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Nice GLib ICE library.
*
* The Initial Developers of the Original Code are Collabora Ltd and Nokia
* Corporation. All Rights Reserved.
*
* Contributors:
* Dafydd Harries, Collabora Ltd.
*
* Alternatively, the contents of this file may be used under the terms of the
* the GNU Lesser General Public License Version 2.1 (the "LGPL"), in which
* case the provisions of LGPL are applicable instead of those above. If you
* wish to allow use of your version of this file only under the terms of the
* LGPL and not to allow others to use your version of this file under the
* MPL, indicate your decision by deleting the provisions above and replace
* them with the notice and other provisions required by the LGPL. If you do
* not delete the provisions above, a recipient may use your version of this
* file under either the MPL or the LGPL.
*/
#ifndef _HTTP_H
#define _HTTP_H
#include "socket.h"
#include "agent.h"
G_BEGIN_DECLS
NiceSocket
*
nice_http_socket_new
(
NiceSocket
*
base_socket
,
NiceAddress
*
addr
,
gchar
*
username
,
gchar
*
password
);
G_END_DECLS
#endif
/* _HTTP_H */
socket/socket.h
View file @
b21caf2e
...
...
@@ -86,6 +86,7 @@ nice_socket_free (NiceSocket *sock);
#include "tcp-bsd.h"
#include "pseudossl.h"
#include "socks5.h"
#include "http.h"
#include "turn.h"
#include "tcp-turn.h"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment