]> git.sesse.net Git - pistorm/blob - a314/a314device/sockets.c
Add A314 emulation
[pistorm] / a314 / a314device / sockets.c
1 #include <proto/exec.h>
2
3 #include "sockets.h"
4
5 struct List active_sockets;
6
7 struct Socket *send_queue_head = NULL;
8 struct Socket *send_queue_tail = NULL;
9
10 static UBYTE next_stream_id = 1;
11
12 extern void NewList(struct List *l);
13
14 void init_sockets()
15 {
16         NewList(&active_sockets);
17 }
18
19 struct Socket *find_socket(void *sig_task, ULONG socket)
20 {
21         for (struct Node *node = active_sockets.lh_Head; node->ln_Succ != NULL; node = node->ln_Succ)
22         {
23                 struct Socket *s = (struct Socket *)node;
24                 if (s->sig_task == sig_task && s->socket == socket)
25                         return s;
26         }
27         return NULL;
28 }
29
30 struct Socket *find_socket_by_stream_id(UBYTE stream_id)
31 {
32         for (struct Node *node = active_sockets.lh_Head; node->ln_Succ != NULL; node = node->ln_Succ)
33         {
34                 struct Socket *s = (struct Socket *)node;
35                 if (s->stream_id == stream_id)
36                         return s;
37         }
38         return NULL;
39 }
40
41 static UBYTE allocate_stream_id()
42 {
43         // Bug: If all stream ids are allocated then this loop won't terminate.
44
45         while (1)
46         {
47                 UBYTE stream_id = next_stream_id;
48                 next_stream_id += 2;
49                 if (find_socket_by_stream_id(stream_id) == NULL)
50                         return stream_id;
51         }
52 }
53
54 static void free_stream_id(UBYTE stream_id)
55 {
56         // Currently do nothing.
57         // Could speed up allocate_stream_id using a bitmap?
58 }
59
60 struct Socket *create_socket(struct Task *task, ULONG id)
61 {
62         struct Socket *s = (struct Socket *)AllocMem(sizeof(struct Socket), MEMF_CLEAR);
63         s->sig_task = task;
64         s->socket = id;
65         s->stream_id = allocate_stream_id();
66         AddTail(&active_sockets, (struct Node *)s);
67         return s;
68 }
69
70 void delete_socket(struct Socket *s)
71 {
72         Remove((struct Node *)s);
73         free_stream_id(s->stream_id);
74         FreeMem(s, sizeof(struct Socket));
75 }
76
77 void add_to_send_queue(struct Socket *s, UWORD required_length)
78 {
79         s->send_queue_required_length = required_length;
80         s->next_in_send_queue = NULL;
81
82         if (send_queue_head == NULL)
83                 send_queue_head = s;
84         else
85                 send_queue_tail->next_in_send_queue = s;
86         send_queue_tail = s;
87
88         s->flags |= SOCKET_IN_SEND_QUEUE;
89 }
90
91 void remove_from_send_queue(struct Socket *s)
92 {
93         if (s->flags & SOCKET_IN_SEND_QUEUE)
94         {
95                 if (send_queue_head == s)
96                 {
97                         send_queue_head = s->next_in_send_queue;
98                         if (send_queue_head == NULL)
99                                 send_queue_tail = NULL;
100                 }
101                 else
102                 {
103                         struct Socket *curr = send_queue_head;
104                         while (curr->next_in_send_queue != s)
105                                 curr = curr->next_in_send_queue;
106
107                         curr->next_in_send_queue = s->next_in_send_queue;
108                         if (send_queue_tail == s)
109                                 send_queue_tail = curr;
110                 }
111
112                 s->next_in_send_queue = NULL;
113                 s->flags &= ~SOCKET_IN_SEND_QUEUE;
114         }
115 }