Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
8fce5b42
Commit
8fce5b42
authored
Jan 18, 2014
by
Damien George
Browse files
Merge pull request #194 from pfalcon/socket
Add lean ("raw") socket module.
parents
6b21538e
fc926082
Changes
3
Hide whitespace changes
Inline
Side-by-side
unix/Makefile
View file @
8fce5b42
...
@@ -25,6 +25,7 @@ endif
...
@@ -25,6 +25,7 @@ endif
SRC_C
=
\
SRC_C
=
\
main.c
\
main.c
\
file.c
\
file.c
\
socket.c
\
OBJ
=
$(
addprefix
$(BUILD)
/,
$(SRC_C:.c=.o)
)
$(PY_O)
OBJ
=
$(
addprefix
$(BUILD)
/,
$(SRC_C:.c=.o)
)
$(PY_O)
LIB
=
-lreadline
LIB
=
-lreadline
...
...
unix/main.c
View file @
8fce5b42
...
@@ -21,6 +21,7 @@
...
@@ -21,6 +21,7 @@
#endif
#endif
extern
const
mp_obj_fun_native_t
mp_builtin_open_obj
;
extern
const
mp_obj_fun_native_t
mp_builtin_open_obj
;
void
rawsocket_init
();
static
void
execute_from_lexer
(
mp_lexer_t
*
lex
,
mp_parse_input_kind_t
input_kind
,
bool
is_repl
)
{
static
void
execute_from_lexer
(
mp_lexer_t
*
lex
,
mp_parse_input_kind_t
input_kind
,
bool
is_repl
)
{
if
(
lex
==
NULL
)
{
if
(
lex
==
NULL
)
{
...
@@ -223,6 +224,7 @@ int main(int argc, char **argv) {
...
@@ -223,6 +224,7 @@ int main(int argc, char **argv) {
rt_store_name
(
qstr_from_str_static
(
"test"
),
test_obj_new
(
42
));
rt_store_name
(
qstr_from_str_static
(
"test"
),
test_obj_new
(
42
));
rt_store_name
(
qstr_from_str_static
(
"open"
),
(
mp_obj_t
)
&
mp_builtin_open_obj
);
rt_store_name
(
qstr_from_str_static
(
"open"
),
(
mp_obj_t
)
&
mp_builtin_open_obj
);
rawsocket_init
();
// Here is some example code to create a class and instance of that class.
// Here is some example code to create a class and instance of that class.
// First is the Python, then the C code.
// First is the Python, then the C code.
...
...
unix/socket.c
0 → 100644
View file @
8fce5b42
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>
#include "nlr.h"
#include "misc.h"
#include "mpconfig.h"
#include "mpqstr.h"
#include "obj.h"
#include "objtuple.h"
#include "objarray.h"
#include "runtime.h"
#include "stream.h"
#define MICROPY_SOCKET_EXTRA (0)
typedef
struct
_mp_obj_socket_t
{
mp_obj_base_t
base
;
int
fd
;
}
mp_obj_socket_t
;
static
const
mp_obj_type_t
rawsocket_type
;
// Helper functions
#define RAISE_ERRNO(err_flag, error_val) \
{ if (err_flag == -1) \
{ nlr_jump(mp_obj_new_exception_msg_varg(MP_QSTR_OSError, "[Errno %d]", error_val)); } }
static
void
get_buffer
(
mp_obj_t
obj
,
buffer_info_t
*
bufinfo
)
{
mp_obj_base_t
*
o
=
(
mp_obj_base_t
*
)
obj
;
if
(
o
->
type
->
buffer_p
.
get_buffer
==
NULL
)
{
goto
error
;
}
o
->
type
->
buffer_p
.
get_buffer
(
o
,
bufinfo
,
BUFFER_READ
);
if
(
bufinfo
->
buf
==
NULL
)
{
goto
error
;
}
return
;
error:
nlr_jump
(
mp_obj_new_exception_msg
(
MP_QSTR_TypeError
,
"Operation not supported"
));
}
static
mp_obj_socket_t
*
socket_new
(
int
fd
)
{
mp_obj_socket_t
*
o
=
m_new_obj
(
mp_obj_socket_t
);
o
->
base
.
type
=
&
rawsocket_type
;
o
->
fd
=
fd
;
return
o
;
}
static
void
socket_print
(
void
(
*
print
)(
void
*
env
,
const
char
*
fmt
,
...),
void
*
env
,
mp_obj_t
self_in
,
mp_print_kind_t
kind
)
{
mp_obj_socket_t
*
self
=
self_in
;
print
(
env
,
"<_socket %d>"
,
self
->
fd
);
}
static
machine_int_t
socket_read
(
mp_obj_t
o_in
,
void
*
buf
,
machine_uint_t
size
,
int
*
errcode
)
{
mp_obj_socket_t
*
o
=
o_in
;
machine_int_t
r
=
read
(
o
->
fd
,
buf
,
size
);
if
(
r
==
-
1
)
{
*
errcode
=
errno
;
}
return
r
;
}
static
machine_int_t
socket_write
(
mp_obj_t
o_in
,
const
void
*
buf
,
machine_uint_t
size
,
int
*
errcode
)
{
mp_obj_socket_t
*
o
=
o_in
;
machine_int_t
r
=
write
(
o
->
fd
,
buf
,
size
);
if
(
r
==
-
1
)
{
*
errcode
=
errno
;
}
return
r
;
}
static
mp_obj_t
socket_close
(
mp_obj_t
self_in
)
{
mp_obj_socket_t
*
self
=
self_in
;
close
(
self
->
fd
);
return
mp_const_none
;
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
socket_close_obj
,
socket_close
);
static
mp_obj_t
socket_connect
(
mp_obj_t
self_in
,
mp_obj_t
addr_in
)
{
mp_obj_socket_t
*
self
=
self_in
;
buffer_info_t
bufinfo
;
get_buffer
(
addr_in
,
&
bufinfo
);
int
r
=
connect
(
self
->
fd
,
(
const
struct
sockaddr
*
)
bufinfo
.
buf
,
bufinfo
.
len
);
RAISE_ERRNO
(
r
,
errno
);
return
mp_const_none
;
}
static
MP_DEFINE_CONST_FUN_OBJ_2
(
socket_connect_obj
,
socket_connect
);
static
mp_obj_t
socket_bind
(
mp_obj_t
self_in
,
mp_obj_t
addr_in
)
{
mp_obj_socket_t
*
self
=
self_in
;
buffer_info_t
bufinfo
;
get_buffer
(
addr_in
,
&
bufinfo
);
int
r
=
bind
(
self
->
fd
,
(
const
struct
sockaddr
*
)
bufinfo
.
buf
,
bufinfo
.
len
);
RAISE_ERRNO
(
r
,
errno
);
return
mp_const_none
;
}
static
MP_DEFINE_CONST_FUN_OBJ_2
(
socket_bind_obj
,
socket_bind
);
static
mp_obj_t
socket_listen
(
mp_obj_t
self_in
,
mp_obj_t
backlog_in
)
{
mp_obj_socket_t
*
self
=
self_in
;
int
r
=
listen
(
self
->
fd
,
MP_OBJ_SMALL_INT_VALUE
(
backlog_in
));
RAISE_ERRNO
(
r
,
errno
);
return
mp_const_none
;
}
static
MP_DEFINE_CONST_FUN_OBJ_2
(
socket_listen_obj
,
socket_listen
);
static
mp_obj_t
socket_accept
(
mp_obj_t
self_in
)
{
mp_obj_socket_t
*
self
=
self_in
;
struct
sockaddr
addr
;
socklen_t
addr_len
=
sizeof
(
addr
);
int
fd
=
accept
(
self
->
fd
,
&
addr
,
&
addr_len
);
RAISE_ERRNO
(
fd
,
errno
);
mp_obj_tuple_t
*
t
=
mp_obj_new_tuple
(
2
,
NULL
);
t
->
items
[
0
]
=
socket_new
(
fd
);
t
->
items
[
1
]
=
mp_obj_new_bytearray
(
addr_len
,
&
addr
);
return
t
;
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
socket_accept_obj
,
socket_accept
);
static
mp_obj_t
socket_make_new
(
mp_obj_t
type_in
,
uint
n_args
,
uint
n_kw
,
const
mp_obj_t
*
args
)
{
int
family
=
AF_INET
;
int
type
=
SOCK_STREAM
;
int
proto
=
0
;
if
(
n_args
>
0
)
{
assert
(
MP_OBJ_IS_SMALL_INT
(
args
[
0
]));
family
=
MP_OBJ_SMALL_INT_VALUE
(
args
[
0
]);
if
(
n_args
>
1
)
{
assert
(
MP_OBJ_IS_SMALL_INT
(
args
[
1
]));
type
=
MP_OBJ_SMALL_INT_VALUE
(
args
[
1
]);
if
(
n_args
>
2
)
{
assert
(
MP_OBJ_IS_SMALL_INT
(
args
[
2
]));
proto
=
MP_OBJ_SMALL_INT_VALUE
(
args
[
2
]);
}
}
}
int
fd
=
socket
(
family
,
type
,
proto
);
RAISE_ERRNO
(
fd
,
errno
);
return
socket_new
(
fd
);
}
static
const
mp_method_t
rawsocket_type_methods
[]
=
{
{
"read"
,
&
mp_stream_read_obj
},
{
"readall"
,
&
mp_stream_readall_obj
},
{
"readline"
,
&
mp_stream_unbuffered_readline_obj
},
{
"write"
,
&
mp_stream_write_obj
},
{
"connect"
,
&
socket_connect_obj
},
{
"bind"
,
&
socket_bind_obj
},
{
"listen"
,
&
socket_listen_obj
},
{
"accept"
,
&
socket_accept_obj
},
{
"close"
,
&
socket_close_obj
},
#if MICROPY_SOCKET_EXTRA
{
"recv"
,
&
mp_stream_read_obj
},
{
"send"
,
&
mp_stream_write_obj
},
#endif
{
NULL
,
NULL
},
};
static
const
mp_obj_type_t
rawsocket_type
=
{
{
&
mp_const_type
},
"socket"
,
.
print
=
socket_print
,
.
make_new
=
socket_make_new
,
.
getiter
=
NULL
,
.
iternext
=
NULL
,
.
stream_p
=
{
.
read
=
socket_read
,
.
write
=
socket_write
,
},
.
methods
=
rawsocket_type_methods
,
};
static
mp_obj_t
mod_socket_htons
(
mp_obj_t
arg
)
{
return
MP_OBJ_NEW_SMALL_INT
(
htons
(
MP_OBJ_SMALL_INT_VALUE
(
arg
)));
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
mod_socket_htons_obj
,
mod_socket_htons
);
static
mp_obj_t
mod_socket_inet_aton
(
mp_obj_t
arg
)
{
assert
(
MP_OBJ_IS_TYPE
(
arg
,
&
str_type
));
const
char
*
s
=
qstr_str
(
mp_obj_str_get
(
arg
));
struct
in_addr
addr
;
if
(
!
inet_aton
(
s
,
&
addr
))
{
nlr_jump
(
mp_obj_new_exception_msg
(
MP_QSTR_OSError
,
"Invalid IP address"
));
}
return
mp_obj_new_int
(
addr
.
s_addr
);
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
mod_socket_inet_aton_obj
,
mod_socket_inet_aton
);
#if MICROPY_SOCKET_EXTRA
static
mp_obj_t
mod_socket_gethostbyname
(
mp_obj_t
arg
)
{
assert
(
MP_OBJ_IS_TYPE
(
arg
,
&
str_type
));
const
char
*
s
=
qstr_str
(
mp_obj_str_get
(
arg
));
struct
hostent
*
h
=
gethostbyname
(
s
);
if
(
h
==
NULL
)
{
nlr_jump
(
mp_obj_new_exception_msg_varg
(
MP_QSTR_OSError
,
"[Errno %d]"
,
errno
));
}
assert
(
h
->
h_length
==
4
);
return
mp_obj_new_int
(
*
(
int
*
)
*
h
->
h_addr_list
);
}
static
MP_DEFINE_CONST_FUN_OBJ_1
(
mod_socket_gethostbyname_obj
,
mod_socket_gethostbyname
);
#endif
static
mp_obj_t
mod_socket_getaddrinfo
(
int
n_args
,
const
mp_obj_t
*
args
)
{
// TODO: Implement all args
assert
(
n_args
==
2
);
assert
(
MP_OBJ_IS_TYPE
(
args
[
0
],
&
str_type
));
const
char
*
host
=
qstr_str
(
mp_obj_str_get
(
args
[
0
]));
const
char
*
serv
=
NULL
;
// getaddrinfo accepts port in string notation, so however
// it may seem stupid, we need to convert int to str
if
(
MP_OBJ_IS_SMALL_INT
(
args
[
1
]))
{
int
port
=
MP_OBJ_SMALL_INT_VALUE
(
args
[
1
]);
static
char
buf
[
20
];
sprintf
(
buf
,
"%d"
,
port
);
serv
=
buf
;
}
else
{
serv
=
qstr_str
(
mp_obj_str_get
(
args
[
1
]));
}
struct
addrinfo
hints
;
struct
addrinfo
*
addr
;
memset
(
&
hints
,
0
,
sizeof
(
hints
));
int
res
=
getaddrinfo
(
host
,
serv
,
NULL
/*&hints*/
,
&
addr
);
if
(
res
!=
0
)
{
nlr_jump
(
mp_obj_new_exception_msg_varg
(
MP_QSTR_OSError
,
"[addrinfo error %d]"
,
res
));
}
assert
(
addr
);
mp_obj_t
list
=
rt_build_list
(
0
,
NULL
);
for
(;
addr
;
addr
=
addr
->
ai_next
)
{
mp_obj_tuple_t
*
t
=
mp_obj_new_tuple
(
5
,
NULL
);
t
->
items
[
0
]
=
MP_OBJ_NEW_SMALL_INT
(
addr
->
ai_family
);
t
->
items
[
1
]
=
MP_OBJ_NEW_SMALL_INT
(
addr
->
ai_socktype
);
t
->
items
[
2
]
=
MP_OBJ_NEW_SMALL_INT
(
addr
->
ai_protocol
);
// "canonname will be a string representing the canonical name of the host
// if AI_CANONNAME is part of the flags argument; else canonname will be empty." ??
if
(
addr
->
ai_canonname
)
{
t
->
items
[
3
]
=
MP_OBJ_NEW_QSTR
(
qstr_from_strn_copy
(
addr
->
ai_canonname
,
strlen
(
addr
->
ai_canonname
)));
}
else
{
t
->
items
[
3
]
=
mp_const_none
;
}
t
->
items
[
4
]
=
mp_obj_new_bytearray
(
addr
->
ai_addrlen
,
addr
->
ai_addr
);
rt_list_append
(
list
,
t
);
}
return
list
;
}
static
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN
(
mod_socket_getaddrinfo_obj
,
2
,
6
,
mod_socket_getaddrinfo
);
extern
mp_obj_type_t
sockaddr_in_type
;
#define STORE_INT_CONST(m, name) rt_store_attr(m, qstr_from_str_static(#name), MP_OBJ_NEW_SMALL_INT(name))
void
socket_init
()
{
mp_obj_t
m
=
mp_obj_new_module
(
qstr_from_str_static
(
"rawsocket"
));
rt_store_attr
(
m
,
qstr_from_str_static
(
"socket"
),
(
mp_obj_t
)
&
rawsocket_type
);
#if MICROPY_SOCKET_EXTRA
rt_store_attr
(
m
,
qstr_from_str_static
(
"sockaddr_in"
),
(
mp_obj_t
)
&
sockaddr_in_type
);
rt_store_attr
(
m
,
qstr_from_str_static
(
"htons"
),
(
mp_obj_t
)
&
mod_socket_htons_obj
);
rt_store_attr
(
m
,
qstr_from_str_static
(
"inet_aton"
),
(
mp_obj_t
)
&
mod_socket_inet_aton_obj
);
rt_store_attr
(
m
,
qstr_from_str_static
(
"gethostbyname"
),
(
mp_obj_t
)
&
mod_socket_gethostbyname_obj
);
#endif
rt_store_attr
(
m
,
qstr_from_str_static
(
"getaddrinfo"
),
(
mp_obj_t
)
&
mod_socket_getaddrinfo_obj
);
STORE_INT_CONST
(
m
,
AF_UNIX
);
STORE_INT_CONST
(
m
,
AF_INET
);
STORE_INT_CONST
(
m
,
AF_INET6
);
STORE_INT_CONST
(
m
,
SOCK_STREAM
);
STORE_INT_CONST
(
m
,
SOCK_DGRAM
);
STORE_INT_CONST
(
m
,
SOCK_RAW
);
rt_store_name
(
qstr_from_str_static
(
"rawsocket"
),
m
);
}
Write
Preview
Supports
Markdown
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