summaryrefslogtreecommitdiff
path: root/netio.c
diff options
context:
space:
mode:
Diffstat (limited to 'netio.c')
-rw-r--r--netio.c185
1 files changed, 185 insertions, 0 deletions
diff --git a/netio.c b/netio.c
new file mode 100644
index 0000000..6fc4d4b
--- /dev/null
+++ b/netio.c
@@ -0,0 +1,185 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "meta.h"
+#include "files.h"
+#include "peer.h"
+#include "netio.h"
+
+LIST_HEAD(btclist, btchunk) chead;
+LIST_HEAD(btrlist, btrequest) rhead;
+
+struct btrequest *allocrequest(struct btmeta *, struct btpeer *, int, off_t, off_t);
+int freerequest(struct btmeta *, struct btpeer *, int n, off_t, off_t);
+struct btchunk *allocchunk(struct btmeta *, int);
+int freechunk(struct btmeta *, int);
+
+/* DON'T FORGET:
+
+LIST_INIT(&chead);
+LIST_INIT(&rhead);
+
+ */
+
+struct btrequest *
+btallocrequest(struct btmeta *mp, struct btpeer *p, int n, off_t off, off_t len)
+{
+ struct btrequest *r;
+
+ r = malloc(sizeof(struct btrequest));
+ assert(r);
+
+ r->peer = p;
+ r->offset = off;
+ r->length = len;
+ r->chunk = allocchunk(mp, n);
+ r->transmitted = 0;
+
+ LIST_INSERT_HEAD(&rhead, r, link);
+
+ return r;
+}
+
+int
+btfreerequest(struct btmeta *mp, struct btpeer *p, int n, off_t off, off_t len)
+{
+ struct btrequest *r, *nxt;
+
+ for (r = LIST_FIRST(&rhead); r != LIST_END(&rhead); r = nxt) {
+ nxt = LIST_NEXT(r, link);
+ if (r->peer == p && r->offset == off && r->length == len) {
+ if (freechunk(mp, r->chunk->piece) == -1)
+ return -1;
+ LIST_REMOVE(r, link);
+ free(r);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int
+btwriterequest(struct btpeer *p, int n, off_t off, off_t len)
+{
+ struct btrequest *r, *nxt;
+
+ for (r = LIST_FIRST(&rhead); r != LIST_END(&rhead); r = nxt) {
+ nxt = LIST_NEXT(r, link);
+ if (r->peer == p && r->offset == off && r->length == len) {
+ memcpy(r->chunk->data + r->offset, p->msgbuf, p->buflen);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+struct btchunk *
+allocchunk(struct btmeta *mp, int n)
+{
+ struct btchunk *p;
+
+ /* look if we have already that chunk */
+ LIST_FOREACH(p, &chead, link) {
+ if (p->piece == n) {
+ ++p->ref;
+ return p;
+ }
+ }
+
+ /* not found, allocate a new one */
+ p = malloc(sizeof(struct btchunk));
+ assert(p);
+ p->ref = 1;
+ p->piece = n;
+ p->sha1 = mp->pieces[n];
+ p->len = btsizeofpiece(mp, n);
+ p->data = calloc(p->len, sizeof(char));
+ assert(p->data);
+ if (btisset(mp->bitfield, n))
+ btread(mp, p->data, p->len, n);
+
+ return p;
+}
+
+int
+freechunk(struct btmeta *mp, int n)
+{
+ struct btchunk *p, *nxt;
+
+ for (p = LIST_FIRST(&chead); p != LIST_END(&chead); p = nxt) {
+ nxt = LIST_NEXT(p, link);
+ if (p->piece == n) {
+ /* do we have it already? */
+ if (btisset(mp->bitfield, n))
+ return 1;
+
+ /* check and write */
+ if (!btcheck(p->sha1, p->data, p->len) || !btwrite(mp, p->data, p->len, n))
+ return -1;
+ btsetbit(mp->bitfield, n);
+
+ if (--p->ref <= 0) {
+ /* nobody refers anymore to this piece */
+ LIST_REMOVE(p, link);
+ free(p->data);
+ free(p);
+ }
+
+ /* announce all that we have that piece */
+ return 0;
+ }
+ }
+
+ /* nothing found */
+ return -1;
+}
+
+
+
+
+#if 0
+
+/* put message on queue */
+/* needed vars:
+ data, length,
+ send/recv (*fp)()
+ socket
+ */
+
+void
+btputqueue(struct btqueue *head, struct btpeer *p, ssize_t (*fp)(int, void *, size_t, int))
+{
+ struct btqentry *q;
+
+ q = malloc(sizeof(struct btqentry));
+ assert(q);
+
+ q->data = p->data + p->offset;
+ q->length = p->length;
+ q->doit = fp;
+ q->sockd = p->sockd;
+
+ SIMPLEQ_INSERT_TAIL(head, q, link);
+}
+
+int
+nonblock(int s)
+{
+ int flags;
+
+ flags = fcntl(s, F_GETFL);
+ if (flags < 0 || fcntl(s, F_SETFL, flags|O_NONBLOCK) < 0)
+ return -1;
+
+ return s;
+}
+
+#endif