Allow binding to arbitrary port

This commit is contained in:
Baptiste Wicht 2016-09-19 20:42:18 +02:00
parent eb98f9f472
commit 28dc3fff33
5 changed files with 82 additions and 1 deletions

View File

@ -159,6 +159,13 @@ std::expected<void> listen(socket_fd_t socket_fd, bool listen);
*/ */
std::expected<size_t> client_bind(socket_fd_t socket_fd, network::ip::address address); std::expected<size_t> client_bind(socket_fd_t socket_fd, network::ip::address address);
/*!
* \brief Bind a socket datagram as a client (bind a local random port)
* \param socket_fd The file descriptor of the packet
* \return the allocated port on success and a negative error code otherwise
*/
std::expected<size_t> client_bind(socket_fd_t socket_fd, network::ip::address address, size_t port);
/*! /*!
* \brief Unbind a socket datagram as a client * \brief Unbind a socket datagram as a client
* \param socket_fd The file descriptor of the packet * \param socket_fd The file descriptor of the packet

View File

@ -488,7 +488,27 @@ std::expected<size_t> network::client_bind(socket_fd_t socket_fd, network::ip::a
switch(datagram_protocol(socket.protocol)){ switch(datagram_protocol(socket.protocol)){
case socket_protocol::UDP: case socket_protocol::UDP:
return network::udp::client_bind(socket, 53, address); return network::udp::client_bind(socket, /* TODO PORT */ 53, address);
default:
return std::make_unexpected<size_t>(std::ERROR_SOCKET_INVALID_TYPE_PROTOCOL);
}
}
std::expected<size_t> network::client_bind(socket_fd_t socket_fd, network::ip::address address, size_t port){
if(!scheduler::has_socket(socket_fd)){
return std::make_unexpected<size_t>(std::ERROR_SOCKET_INVALID_FD);
}
auto& socket = scheduler::get_socket(socket_fd);
if(socket.type != socket_type::DGRAM){
return std::make_unexpected<size_t>(std::ERROR_SOCKET_INVALID_TYPE);
}
switch(datagram_protocol(socket.protocol)){
case socket_protocol::UDP:
return network::udp::client_bind(socket, port, address);
default: default:
return std::make_unexpected<size_t>(std::ERROR_SOCKET_INVALID_TYPE_PROTOCOL); return std::make_unexpected<size_t>(std::ERROR_SOCKET_INVALID_TYPE_PROTOCOL);

View File

@ -443,6 +443,15 @@ void sc_client_bind(interrupt::syscall_regs* regs){
regs->rax = expected_to_i64(status); regs->rax = expected_to_i64(status);
} }
void sc_client_bind_port(interrupt::syscall_regs* regs){
auto socket_fd = regs->rbx;
auto server_ip = regs->rcx;
auto port = regs->rdx;
auto status = network::client_bind(socket_fd, server_ip, port);
regs->rax = expected_to_i64(status);
}
void sc_client_unbind(interrupt::syscall_regs* regs){ void sc_client_unbind(interrupt::syscall_regs* regs){
auto socket_fd = regs->rbx; auto socket_fd = regs->rbx;
@ -754,6 +763,10 @@ void system_call_entry(interrupt::syscall_regs* regs){
sc_receive(regs); sc_receive(regs);
break; break;
case 0x300D:
sc_client_bind_port(regs);
break;
// Special system calls // Special system calls
case 0x6666: case 0x6666:

View File

@ -122,6 +122,14 @@ std::expected<void> listen(size_t socket_fd, bool l);
*/ */
std::expected<size_t> client_bind(size_t socket_fd, tlib::ip::address server); std::expected<size_t> client_bind(size_t socket_fd, tlib::ip::address server);
/*!
* \brief Bind a destination to the datagram socket
* \param socket_fd The socket file descriptor
* \param server The server address
* \return the local port, or an error
*/
std::expected<size_t> client_bind(size_t socket_fd, tlib::ip::address server, size_t port);
/*! /*!
* \brief Unbind from destination from the datagram socket * \brief Unbind from destination from the datagram socket
* \param socket_fd The socket file descriptor * \param socket_fd The socket file descriptor
@ -220,6 +228,12 @@ struct socket {
*/ */
void client_bind(tlib::ip::address server); void client_bind(tlib::ip::address server);
/*!
* \brief Bind the socket as a client
* \param server The IP address
*/
void client_bind(tlib::ip::address server, size_t port);
/*! /*!
* \brief Unbind the client socket * \brief Unbind the client socket
*/ */

View File

@ -154,6 +154,20 @@ std::expected<size_t> tlib::client_bind(size_t socket_fd, tlib::ip::address serv
} }
} }
std::expected<size_t> tlib::client_bind(size_t socket_fd, tlib::ip::address server, size_t port) {
int64_t code;
asm volatile("mov rax, 0x300D; mov rbx, %[socket]; mov rcx, %[ip]; mov rdx, %[port]; int 50; mov %[code], rax"
: [code] "=m"(code)
: [socket] "g"(socket_fd), [ip] "g" (size_t(server.raw_address)), [port] "g" (port)
: "rax", "rbx", "rcx");
if (code < 0) {
return std::make_unexpected<size_t, size_t>(-code);
} else {
return std::make_expected<size_t>(code);
}
}
std::expected<void> tlib::client_unbind(size_t socket_fd) { std::expected<void> tlib::client_unbind(size_t socket_fd) {
int64_t code; int64_t code;
asm volatile("mov rax, 0x300A; mov rbx, %[socket]; int 50; mov %[code], rax" asm volatile("mov rax, 0x300A; mov rbx, %[socket]; int 50; mov %[code], rax"
@ -315,6 +329,19 @@ void tlib::socket::client_bind(tlib::ip::address server) {
} }
} }
void tlib::socket::client_bind(tlib::ip::address server, size_t port) {
if (!good() || !open()) {
return;
}
auto status = tlib::client_bind(fd, server, port);
if (!status) {
_bound = false;
} else {
error_code = status.error();
}
}
void tlib::socket::client_unbind() { void tlib::socket::client_unbind() {
if (!good() || !open()) { if (!good() || !open()) {
return; return;