|
From: <mrv...@us...> - 2008-04-19 23:07:57
|
Revision: 29
http://dawnofinfinity.svn.sourceforge.net/dawnofinfinity/?rev=29&view=rev
Author: mrvacbob
Date: 2008-04-19 16:07:55 -0700 (Sat, 19 Apr 2008)
Log Message:
-----------
The last set of changes I made to this code - not sure what they do, but it was along the way to UDP.
Modified Paths:
--------------
trunk/net.cpp
trunk/net.h
trunk/queue.h
trunk/set.h
Modified: trunk/net.cpp
===================================================================
--- trunk/net.cpp 2007-06-03 00:48:17 UTC (rev 28)
+++ trunk/net.cpp 2008-04-19 23:07:55 UTC (rev 29)
@@ -36,7 +36,7 @@
tcp.sock = fd;
tcp.curp = udp.curp = NULL;
recv_remain = recv_done = send_remain = send_done = 0;
- recievebuf = (Packet)GC_malloc(2);
+ tcp.recievebuf = (Packet)GC_malloc(2);
ccontext = NULL;
fcntl(tcp.sock,F_SETFL,O_NONBLOCK);
@@ -58,6 +58,9 @@
getpeername(tcp.sock, (sockaddr*)&sin, &len);
connect(udp.sock, (sockaddr*)&sin, len);
}
+
+ tcp.recievebuf = (Packet)GC_malloc(4);
+ udp.recievebuf = (Packet)GC_malloc(4);
}
Connection::~Connection()
@@ -65,23 +68,118 @@
close(tcp.sock);
close(udp.sock);
- FD_CLR(tcp.sock, &net->active_fds);
- FD_CLR(udp.sock, &net->active_fds);
+ net->unregister_fd(tcp.sock);
+ net->unregister_fd(udp.sock);
}
void Connection::enqueue(Packet p, enum tcp_udp pt)
{
- ProtocolConn pc = pt == p_tcp ? tcp : udp;
+ ProtocolConn *pc = pt == p_tcp ? &tcp : &udp;
- pc.transmitq.push(p);
- FD_SET(pc.sock, &net->writing_fds);
+ pc->transmitq.push(p);
+ net->request_write(pc->sock);
}
-int Connection::task()
+int Connection::task_send(bool tcp_ready, bool udp_ready)
+{
+ if (tcp_ready) {
+ if (!tcp.curp) {
+ if (tcp.transmitq.is_empty()) net->unrequest_write(tcp.sock);
+ tcp.curp = tcp.transmitq.pop();
+ send_remain = tcp.curp->size();
+ }
+
+ ssize_t sent = send(tcp.sock,&tcp.curp->data->data[send_done],send_remain,0);
+
+ if (sent == -1) {
+ perror("send");
+ if (errno != EAGAIN) return 1;
+ } else if (sent == send_remain) {
+ send_done = send_remain = 0;
+ tcp.curp = NULL;
+ } else {
+ send_remain -= sent;
+ send_done += sent;
+ }
+ }
+
+ if (udp_ready && (udp.curp || !udp.transmitq.is_empty())) {
+ if (!udp.curp) udp.curp = udp.transmitq.pop();
+ ssize_t sent = send(udp.sock,&udp.curp->data->data,udp.curp->size(),0);
+
+ if (sent == -1) {
+ perror("udp send");
+ if (errno != EAGAIN) return 1;
+ } else udp.curp = NULL;
+ }
+
+ return 0;
+}
+
+static ssize_t packet_header_peek(int sock)
{
+ unsigned short psize;
+ int ret = recv(sock, &psize, 2, MSG_PEEK);
+
+ if (ret == 2) return ntohs(psize);
+ else if (ret < 0) return errno == EAGAIN ? 0 : -1;
return 0;
}
+int Connection::task_recv(bool tcp_ready, bool udp_ready)
+{
+ if (tcp_ready) {
+ if (!recv_remain) {
+ ssize_t s = packet_header_peek(tcp.sock);
+ if (s == -1) {
+ perror("header read");
+ return 1;
+ } else if (s == 0) goto udp;
+
+ tcp.recievebuf = (Packet)GC_realloc(tcp.recievebuf,s+4);
+ recv_done = 0; recv_remain = s+4;
+ }
+
+ ssize_t read = recv(tcp.sock, &tcp.recievebuf->data->data[recv_done], recv_remain, 0);
+
+ if (read == -1) {
+ perror("task_recv");
+ if (errno != EAGAIN) return 1;
+ } else if (read == recv_remain) {
+ recv_done = recv_remain = 0;
+ parent->callback->handlepacket(tcp.recievebuf);
+ } else {
+ recv_remain -= read;
+ recv_done += read;
+ }
+ }
+
+ udp:
+
+ if (udp_ready) {
+ ssize_t s = packet_header_peek(udp.sock);
+ if (s == -1) {
+ perror("udp header read");
+ return 1;
+ } else if (s == 0) return 0;
+
+ udp.recievebuf = (Packet)GC_realloc(udp.recievebuf,s+4);
+
+ ssize_t read = recv(udp.sock, udp.recievebuf->data->data, s+4, 0);
+
+ if (read == -1) {
+ perror("task_recv udp");
+ if (errno != EAGAIN) return 1;
+ } else if (read < (s+4)) {
+ //this is probably impossible
+ } else {
+ parent->callback->handlepacket(udp.recievebuf);
+ }
+ }
+
+ return 0;
+}
+
ConnectionGroup::ConnectionGroup(ConnCallback *cc, Net *parent) : callback(cc), parent(parent)
{
}
@@ -130,7 +228,7 @@
fcntl(so,F_SETFL,O_NONBLOCK);
listen(so,SOMAXCONN);
lsock = highfd = so;
- FD_SET(so, &active_fds);
+ register_fd(so);
}
Net::Net(const char *port, NewConnCallback *cc) : ncc(cc)
Modified: trunk/net.h
===================================================================
--- trunk/net.h 2007-06-03 00:48:17 UTC (rev 28)
+++ trunk/net.h 2008-04-19 23:07:55 UTC (rev 29)
@@ -34,12 +34,14 @@
{
union {
struct {
+ uint16_t size;
uint16_t type;
- uint16_t size;
};
unsigned char data[0];
- };
+ } *data;
+
+ int size() {return ntohs(data->size)+4;}
};
typedef struct packetinternals *Packet;
@@ -47,7 +49,7 @@
struct ConnCallbackContext : public Object {};
struct ConnCallback : public Object {
- virtual void handlepacket(Packet *p) = 0;
+ virtual void handlepacket(Packet p) = 0;
};
enum tcp_udp {p_tcp, p_udp};
@@ -56,7 +58,7 @@
{
struct ProtocolConn {
Queue<Packet> transmitq;
- Packet curp;
+ Packet curp, recievebuf;
int sock;
} tcp, udp;
@@ -66,16 +68,15 @@
struct ConnectionGroup *parent;
struct Net *net;
-
- Packet recievebuf;
-
+
struct ConnCallbackContext *ccontext;
Connection(int fd, ConnectionGroup *parent);
~Connection();
void enqueue(Packet p, enum tcp_udp pt = p_tcp);
- int task();
+ int task_recv(bool tcp, bool udp);
+ int task_send(bool tcp, bool udp);
};
struct NewConnCallback : public Object {
@@ -121,6 +122,12 @@
void broadcast(Packet p, enum tcp_udp pt = p_tcp);
+ void request_write(int fd) {FD_SET(fd, &writing_fds);}
+ void unrequest_write(int fd) {FD_CLR(fd, &writing_fds);}
+
+ void register_fd(int fd) {FD_SET(fd, &active_fds);}
+ void unregister_fd(int fd) {FD_CLR(fd, &active_fds);}
+
private:
void setup_listener(const char *port);
};
Modified: trunk/queue.h
===================================================================
--- trunk/queue.h 2007-06-03 00:48:17 UTC (rev 28)
+++ trunk/queue.h 2008-04-19 23:07:55 UTC (rev 29)
@@ -34,18 +34,24 @@
#define QPERFORM_START(_inq, type, varname) \
{ \
Queue<type> *_inq2 = (Queue<type> *)_inq;\
- int _inq_i = _inq2->begin; \
- while(_inq_i != _inq2->end) {\
- const type varname = _inq2->data[_inq_i];_inq2->clear(_inq_i++);
+ size_t _q_b1 = _inq2->begin, _q_b2=0, _q_e1=0, _q_e2=0, _q_iter = 1;\
+ if (_inq2->begin > _inq2->end) {_q_e1 = _inq2->allocated; _q_e2 = _inq2->end; _q_iter = 2;}\
+ else _q_e1 = _inq2->end;\
+ for (int _q_whichpart = 0; _q_whichpart < _q_iter; _q_whichpart++) {\
+ size_t _q_b = _q_whichpart ? _q_b2 : _q_b1;\
+ size_t _q_e = _q_whichpart ? _q_e2 : _q_e1;\
+ for (size_t _q_i = _q_b; _q_i < _q_e; _q_i++) { \
+ const type varname = _inq2->data[_inq_i];
-#define PQPERFORM_START(_inq, varname) QPERFORM_START(_inq, void *, varname)
#define QPERFORM_END() \
- if (_inq_i == _inq2->allocated) _inq_i = 0;\
- };\
+ _inq2->clear(_inq_i++); \
+ }}\
_inq2->begin = _inq2->end = _inq2->filled = 0;\
}
+#define PQPERFORM_START(_inq, varname) QPERFORM_START(_inq, void *, varname)
+
template<typename T>
struct Queue : public Object
{
Modified: trunk/set.h
===================================================================
--- trunk/set.h 2007-06-03 00:48:17 UTC (rev 28)
+++ trunk/set.h 2008-04-19 23:07:55 UTC (rev 29)
@@ -41,9 +41,8 @@
/// A hack to allow the same block of code to operate on two sets without code duplication.
#define TWOSETSPERFORM_START(_inset, _inset2, type, varname) \
{\
- Set<type> *_iset1 = (Set<type> *)_inset, *_iset2 = (Set<type> *)_inset2;\
- for (int _whichset_i = 0; _whichset_i < 2; _whichset_i++) {\
- Set<type> *_iset = _whichset_i ? _iset2 : _iset1; \
+ for (char _whichset_i = 0; _whichset_i < 2; _whichset_i++) {\
+ Set<type> *_iset = _whichset_i ? (Set<type> *)_inset : (Set<type> *)_inset2; \
for (size_t _set_i = 0;_set_i<_iset->filled;) {\
type &varname = _iset->data[_set_i++];\
@@ -103,7 +102,7 @@
}
return false;
}
-
+
void grow() {
size_t newsize = allocated + 16;
data = (T*)GC_realloc(data, sizeof(T[newsize]));
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|