diff options
author | Juan Linietsky <reduzio@gmail.com> | 2014-11-12 11:23:23 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2014-11-12 11:23:23 -0300 |
commit | 6dd8768811cfca5bb831619d93cf870e5d20667f (patch) | |
tree | 9e8837b7c8334855a1bce1bd79ab441edde28129 /drivers/unix | |
parent | c8cd5222a7fa931f072e02b23c5b9d826d0ef548 (diff) |
3D Import Import & UDP
-=-=-=-=-=-=-=-=-=-=-
-Animation Import filter support
-Animation Clip import support
-Animation Optimizer Fixes, Improvements and Visibile Options
-Extremely Experimental UDP support.
Diffstat (limited to 'drivers/unix')
-rw-r--r-- | drivers/unix/os_unix.cpp | 2 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.cpp | 188 | ||||
-rw-r--r-- | drivers/unix/packet_peer_udp_posix.h | 56 |
3 files changed, 246 insertions, 0 deletions
diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index ef4cf644fd..e6458068ea 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -42,6 +42,7 @@ #include "dir_access_unix.h" #include "tcp_server_posix.h" #include "stream_peer_tcp_posix.h" +#include "packet_peer_udp_posix.h" #include <stdarg.h> @@ -115,6 +116,7 @@ void OS_Unix::initialize_core() { #ifndef NO_NETWORK TCPServerPosix::make_default(); StreamPeerTCPPosix::make_default(); + PacketPeerUDPPosix::make_default(); IP_Unix::make_default(); #endif mempool_static = new MemoryPoolStaticMalloc; diff --git a/drivers/unix/packet_peer_udp_posix.cpp b/drivers/unix/packet_peer_udp_posix.cpp new file mode 100644 index 0000000000..d951524d3a --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.cpp @@ -0,0 +1,188 @@ +#include "packet_peer_udp_posix.h" + +#ifdef UNIX_ENABLED + + +#include <errno.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <stdio.h> + +#ifndef NO_FCNTL +#include <sys/fcntl.h> +#else +#include <sys/ioctl.h> +#endif + +#ifdef JAVASCRIPT_ENABLED +#include <arpa/inet.h> +#endif + + +int PacketPeerUDPPosix::get_available_packet_count() const { + + Error err = const_cast<PacketPeerUDPPosix*>(this)->poll(); + if (err!=OK) + return 0; + + return queue_count; +} + +Error PacketPeerUDPPosix::get_packet(const uint8_t **r_buffer,int &r_buffer_size) const{ + + Error err = const_cast<PacketPeerUDPPosix*>(this)->poll(); + if (err!=OK) + return err; + if (queue_count==0) + return ERR_UNAVAILABLE; + + uint32_t size; + rb.read((uint8_t*)&size,4,true); + rb.read((uint8_t*)&packet_ip.host,4,true); + rb.read((uint8_t*)&packet_port,4,true); + rb.read(packet_buffer,size,true); + --queue_count; + *r_buffer=packet_buffer; + r_buffer_size=size; + return OK; + +} +Error PacketPeerUDPPosix::put_packet(const uint8_t *p_buffer,int p_buffer_size){ + + int sock = _get_socket(); + ERR_FAIL_COND_V( sock == -1, FAILED ); + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = htons(peer_port); + addr.sin_addr = *((struct in_addr*)&peer_addr.host); + + errno = 0; + int err; + while ( (err = sendto(sock, p_buffer, p_buffer_size, 0, (struct sockaddr*)&addr, sizeof(addr))) != p_buffer_size) { + + if (errno != EAGAIN) { + return FAILED; + } + } + + return OK; +} + +int PacketPeerUDPPosix::get_max_packet_size() const{ + + return 512; // uhm maybe not +} + +Error PacketPeerUDPPosix::listen(int p_port, int p_recv_buffer_size){ + + close(); + int sock = _get_socket(); + if (sock == -1 ) + return ERR_CANT_CREATE; + sockaddr_in addr = {0}; + addr.sin_family = AF_INET; + addr.sin_port = htons(p_port); + addr.sin_addr.s_addr = INADDR_ANY; + if (bind(sock, (struct sockaddr*)&addr, sizeof(sockaddr_in)) == -1 ) { + close(); + return ERR_UNAVAILABLE; + } + printf("UDP Connection listening on port %i\n", p_port); + rb.resize(nearest_power_of_2(p_recv_buffer_size)); + return OK; +} + +void PacketPeerUDPPosix::close(){ + + if (sockfd != -1) + ::close(sockfd); + sockfd=-1; + rb.resize(8); + queue_count=0; +} + +Error PacketPeerUDPPosix::poll() { + + struct sockaddr_in from = {0}; + socklen_t len = sizeof(struct sockaddr_in); + int ret; + while ( (ret = recvfrom(sockfd, recv_buffer, MIN(sizeof(recv_buffer),rb.data_left()-12), MSG_DONTWAIT, (struct sockaddr*)&from, &len)) > 0) { + rb.write((uint8_t*)&from.sin_addr, 4); + uint32_t port = ntohs(from.sin_port); + rb.write((uint8_t*)&port, 4); + rb.write((uint8_t*)&ret, 4); + rb.write(recv_buffer, ret); + + len = sizeof(struct sockaddr_in); + ++queue_count; + }; + + if (ret == 0 || (ret == -1 && errno != EAGAIN) ) { + close(); + return FAILED; + }; + + return OK; +} +bool PacketPeerUDPPosix::is_listening() const{ + + return sockfd!=-1; +} + +IP_Address PacketPeerUDPPosix::get_packet_address() const { + + return packet_ip; +} + +int PacketPeerUDPPosix::get_packet_port() const{ + + return packet_port; +} + +int PacketPeerUDPPosix::_get_socket() { + + if (sockfd != -1) + return sockfd; + + sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + ERR_FAIL_COND_V( sockfd == -1, -1 ); + //fcntl(sockfd, F_SETFL, O_NONBLOCK); + + return sockfd; +} + + +void PacketPeerUDPPosix::set_send_address(const IP_Address& p_address,int p_port) { + + peer_addr=p_address; + peer_port=p_port; +} + +PacketPeerUDP* PacketPeerUDPPosix::_create() { + + return memnew(PacketPeerUDPPosix); +}; + +void PacketPeerUDPPosix::make_default() { + + PacketPeerUDP::_create = PacketPeerUDPPosix::_create; +}; + + +PacketPeerUDPPosix::PacketPeerUDPPosix() { + + sockfd=-1; + packet_port=0; + queue_count=0; + peer_port=0; +} + +PacketPeerUDPPosix::~PacketPeerUDPPosix() { + + close(); +} +#endif diff --git a/drivers/unix/packet_peer_udp_posix.h b/drivers/unix/packet_peer_udp_posix.h new file mode 100644 index 0000000000..428c3ac37e --- /dev/null +++ b/drivers/unix/packet_peer_udp_posix.h @@ -0,0 +1,56 @@ +#ifndef PACKET_PEER_UDP_POSIX_H +#define PACKET_PEER_UDP_POSIX_H + +#ifdef UNIX_ENABLED + +#include "io/packet_peer_udp.h" +#include "ring_buffer.h" + +class PacketPeerUDPPosix : public PacketPeerUDP { + + + enum { + PACKET_BUFFER_SIZE=65536 + }; + + mutable RingBuffer<uint8_t> rb; + uint8_t recv_buffer[PACKET_BUFFER_SIZE]; + mutable uint8_t packet_buffer[PACKET_BUFFER_SIZE]; + IP_Address packet_ip; + int packet_port; + mutable int queue_count; + int sockfd; + + IP_Address peer_addr; + int peer_port; + + _FORCE_INLINE_ int _get_socket(); + + static PacketPeerUDP* _create(); + +public: + + virtual int get_available_packet_count() const; + virtual Error get_packet(const uint8_t **r_buffer,int &r_buffer_size) const; + virtual Error put_packet(const uint8_t *p_buffer,int p_buffer_size); + + virtual int get_max_packet_size() const; + + virtual Error listen(int p_port,int p_recv_buffer_size=65536); + virtual void close(); + virtual Error poll(); + virtual bool is_listening() const; + + virtual IP_Address get_packet_address() const; + virtual int get_packet_port() const; + + virtual void set_send_address(const IP_Address& p_address,int p_port); + + static void make_default(); + + PacketPeerUDPPosix(); + ~PacketPeerUDPPosix(); +}; + +#endif // PACKET_PEER_UDP_POSIX_H +#endif |