2 * Copyright 2018-2021 Niklas Ekström
5 #include <exec/types.h>
6 #include <exec/interrupts.h>
7 #include <exec/lists.h>
8 #include <exec/memory.h>
9 #include <exec/nodes.h>
10 #include <exec/ports.h>
12 #include <exec/errors.h>
13 #include <exec/libraries.h>
14 #include <exec/devices.h>
15 #include <exec/execbase.h>
17 #include <libraries/dos.h>
19 #include <proto/exec.h>
28 #include "fix_mem_region.h"
33 return (ca->r2a_tail - ca->r2a_head) & 255;
38 return (ca->a2r_tail - ca->a2r_head) & 255;
41 BOOL room_in_a2r(int len)
43 return used_in_a2r() + 3 + len <= 255;
46 void append_a2r_packet(UBYTE type, UBYTE stream_id, UBYTE length, UBYTE *data)
48 UBYTE index = ca->a2r_tail;
49 ca->a2r_buffer[index++] = length;
50 ca->a2r_buffer[index++] = type;
51 ca->a2r_buffer[index++] = stream_id;
52 for (int i = 0; i < (int)length; i++)
53 ca->a2r_buffer[index++] = *data++;
57 void close_socket(struct Socket *s, BOOL should_send_reset)
59 debug_printf("Called close socket\n");
61 if (s->pending_connect != NULL)
63 struct A314_IORequest *ior = s->pending_connect;
64 ior->a314_Request.io_Error = A314_CONNECT_RESET;
65 ReplyMsg((struct Message *)ior);
67 s->pending_connect = NULL;
70 if (s->pending_read != NULL)
72 struct A314_IORequest *ior = s->pending_read;
74 ior->a314_Request.io_Error = A314_READ_RESET;
75 ReplyMsg((struct Message *)ior);
77 s->pending_read = NULL;
80 if (s->pending_write != NULL)
82 struct A314_IORequest *ior = s->pending_write;
84 ior->a314_Request.io_Error = A314_WRITE_RESET; // A314_EOS_RESET == A314_WRITE_RESET
85 ReplyMsg((struct Message *)ior);
87 s->pending_write = NULL;
90 if (s->rq_head != NULL)
92 struct QueuedData *qd = s->rq_head;
95 struct QueuedData *next = qd->next;
96 FreeMem(qd, sizeof(struct QueuedData) + qd->length);
103 remove_from_send_queue(s);
105 // No operations can be pending when SOCKET_CLOSED is set.
106 // However, may not be able to delete socket yet, because is waiting to send PKT_RESET.
107 s->flags |= SOCKET_CLOSED;
109 BOOL should_delete_socket = TRUE;
111 if (should_send_reset)
113 if (send_queue_head == NULL && room_in_a2r(0))
115 append_a2r_packet(PKT_RESET, s->stream_id, 0, NULL);
119 s->flags |= SOCKET_SHOULD_SEND_RESET;
120 add_to_send_queue(s, 0);
121 should_delete_socket = FALSE;
125 if (should_delete_socket)
129 // When a message is received on R2A it is written to this buffer,
130 // to avoid dealing with the issue that R2A is a circular buffer.
131 // This is somewhat inefficient, so may want to change that to read from R2A directly.
132 UBYTE received_packet[256];
134 static void handle_pkt_connect_response(UBYTE length, struct Socket *s)
136 debug_printf("Received a CONNECT RESPONSE packet from rpi\n");
138 if (s->pending_connect == NULL)
140 debug_printf("SERIOUS ERROR: received a CONNECT RESPONSE even though no connect was pending\n");
141 // Should reset stream?
143 else if (length != 1)
145 debug_printf("SERIOUS ERROR: received a CONNECT RESPONSE whose length was not 1\n");
146 // Should reset stream?
150 UBYTE result = received_packet[0];
153 struct A314_IORequest *ior = s->pending_connect;
154 ior->a314_Request.io_Error = A314_CONNECT_OK;
155 ReplyMsg((struct Message *)ior);
157 s->pending_connect = NULL;
161 struct A314_IORequest *ior = s->pending_connect;
162 ior->a314_Request.io_Error = A314_CONNECT_UNKNOWN_SERVICE;
163 ReplyMsg((struct Message *)ior);
165 s->pending_connect = NULL;
167 close_socket(s, FALSE);
172 static void handle_pkt_data(UBYTE length, struct Socket *s)
174 debug_printf("Received a DATA packet from rpi\n");
176 if (s->pending_read != NULL)
178 struct A314_IORequest *ior = s->pending_read;
180 if (ior->a314_Length < length)
181 close_socket(s, TRUE);
184 memcpy(ior->a314_Buffer, received_packet, length);
185 ior->a314_Length = length;
186 ior->a314_Request.io_Error = A314_READ_OK;
187 ReplyMsg((struct Message *)ior);
189 s->pending_read = NULL;
194 struct QueuedData *qd = (struct QueuedData *)AllocMem(sizeof(struct QueuedData) + length, 0);
197 memcpy(qd->data, received_packet, length);
199 if (s->rq_head == NULL)
202 s->rq_tail->next = qd;
207 static void handle_pkt_eos(struct Socket *s)
209 debug_printf("Received a EOS packet from rpi\n");
211 s->flags |= SOCKET_RCVD_EOS_FROM_RPI;
213 if (s->pending_read != NULL)
215 struct A314_IORequest *ior = s->pending_read;
216 ior->a314_Length = 0;
217 ior->a314_Request.io_Error = A314_READ_EOS;
218 ReplyMsg((struct Message *)ior);
220 s->pending_read = NULL;
222 s->flags |= SOCKET_SENT_EOS_TO_APP;
224 if (s->flags & SOCKET_SENT_EOS_TO_RPI)
225 close_socket(s, FALSE);
229 static void handle_r2a_packet(UBYTE type, UBYTE stream_id, UBYTE length)
231 struct Socket *s = find_socket_by_stream_id(stream_id);
233 if (s != NULL && type == PKT_RESET)
235 debug_printf("Received a RESET packet from rpi\n");
236 close_socket(s, FALSE);
240 if (s == NULL || (s->flags & SOCKET_CLOSED))
242 // Ignore this packet. The only packet that can do anything useful on a closed
243 // channel is CONNECT, which is not handled at this time.
247 if (type == PKT_CONNECT_RESPONSE)
249 handle_pkt_connect_response(length, s);
251 else if (type == PKT_DATA)
253 handle_pkt_data(length, s);
255 else if (type == PKT_EOS)
261 void handle_packets_received_r2a()
263 while (used_in_r2a() != 0)
265 UBYTE index = ca->r2a_head;
267 UBYTE len = ca->r2a_buffer[index++];
268 UBYTE type = ca->r2a_buffer[index++];
269 UBYTE stream_id = ca->r2a_buffer[index++];
271 for (int i = 0; i < len; i++)
272 received_packet[i] = ca->r2a_buffer[index++];
274 ca->r2a_head = index;
276 handle_r2a_packet(type, stream_id, len);
280 void handle_room_in_a2r()
282 while (send_queue_head != NULL)
284 struct Socket *s = send_queue_head;
286 if (!room_in_a2r(s->send_queue_required_length))
289 remove_from_send_queue(s);
291 if (s->pending_connect != NULL)
293 struct A314_IORequest *ior = s->pending_connect;
294 int len = ior->a314_Length;
295 append_a2r_packet(PKT_CONNECT, s->stream_id, (UBYTE)len, ior->a314_Buffer);
297 else if (s->pending_write != NULL)
299 struct A314_IORequest *ior = s->pending_write;
300 int len = ior->a314_Length;
302 if (ior->a314_Request.io_Command == A314_WRITE)
304 append_a2r_packet(PKT_DATA, s->stream_id, (UBYTE)len, ior->a314_Buffer);
306 ior->a314_Request.io_Error = A314_WRITE_OK;
307 ReplyMsg((struct Message *)ior);
309 s->pending_write = NULL;
313 append_a2r_packet(PKT_EOS, s->stream_id, 0, NULL);
315 ior->a314_Request.io_Error = A314_EOS_OK;
316 ReplyMsg((struct Message *)ior);
318 s->pending_write = NULL;
320 s->flags |= SOCKET_SENT_EOS_TO_RPI;
322 if (s->flags & SOCKET_SENT_EOS_TO_APP)
323 close_socket(s, FALSE);
326 else if (s->flags & SOCKET_SHOULD_SEND_RESET)
328 append_a2r_packet(PKT_RESET, s->stream_id, 0, NULL);
333 debug_printf("SERIOUS ERROR: Was in send queue but has nothing to send\n");
338 static void handle_app_connect(struct A314_IORequest *ior, struct Socket *s)
340 debug_printf("Received a CONNECT request from application\n");
344 ior->a314_Request.io_Error = A314_CONNECT_SOCKET_IN_USE;
345 ReplyMsg((struct Message *)ior);
347 else if (ior->a314_Length + 3 > 255)
349 ior->a314_Request.io_Error = A314_CONNECT_RESET;
350 ReplyMsg((struct Message *)ior);
354 s = create_socket(ior->a314_Request.io_Message.mn_ReplyPort->mp_SigTask, ior->a314_Socket);
356 s->pending_connect = ior;
359 int len = ior->a314_Length;
360 if (send_queue_head == NULL && room_in_a2r(len))
362 append_a2r_packet(PKT_CONNECT, s->stream_id, (UBYTE)len, ior->a314_Buffer);
366 add_to_send_queue(s, len);
371 static void handle_app_read(struct A314_IORequest *ior, struct Socket *s)
373 debug_printf("Received a READ request from application\n");
375 if (s == NULL || (s->flags & SOCKET_CLOSED))
377 ior->a314_Length = 0;
378 ior->a314_Request.io_Error = A314_READ_RESET;
379 ReplyMsg((struct Message *)ior);
383 if (s->pending_connect != NULL || s->pending_read != NULL)
385 ior->a314_Length = 0;
386 ior->a314_Request.io_Error = A314_READ_RESET;
387 ReplyMsg((struct Message *)ior);
389 close_socket(s, TRUE);
391 else if (s->rq_head != NULL)
393 struct QueuedData *qd = s->rq_head;
394 int len = qd->length;
396 if (ior->a314_Length < len)
398 ior->a314_Length = 0;
399 ior->a314_Request.io_Error = A314_READ_RESET;
400 ReplyMsg((struct Message *)ior);
402 close_socket(s, TRUE);
406 s->rq_head = qd->next;
407 if (s->rq_head == NULL)
410 memcpy(ior->a314_Buffer, qd->data, len);
411 FreeMem(qd, sizeof(struct QueuedData) + len);
413 ior->a314_Length = len;
414 ior->a314_Request.io_Error = A314_READ_OK;
415 ReplyMsg((struct Message *)ior);
418 else if (s->flags & SOCKET_RCVD_EOS_FROM_RPI)
420 ior->a314_Length = 0;
421 ior->a314_Request.io_Error = A314_READ_EOS;
422 ReplyMsg((struct Message *)ior);
424 s->flags |= SOCKET_SENT_EOS_TO_APP;
426 if (s->flags & SOCKET_SENT_EOS_TO_RPI)
427 close_socket(s, FALSE);
430 s->pending_read = ior;
434 static void handle_app_write(struct A314_IORequest *ior, struct Socket *s)
436 debug_printf("Received a WRITE request from application\n");
438 if (s == NULL || (s->flags & SOCKET_CLOSED))
440 ior->a314_Length = 0;
441 ior->a314_Request.io_Error = A314_WRITE_RESET;
442 ReplyMsg((struct Message *)ior);
446 int len = ior->a314_Length;
447 if (s->pending_connect != NULL || s->pending_write != NULL || (s->flags & SOCKET_RCVD_EOS_FROM_APP) || len + 3 > 255)
449 ior->a314_Length = 0;
450 ior->a314_Request.io_Error = A314_WRITE_RESET;
451 ReplyMsg((struct Message *)ior);
453 close_socket(s, TRUE);
457 if (send_queue_head == NULL && room_in_a2r(len))
459 append_a2r_packet(PKT_DATA, s->stream_id, (UBYTE)len, ior->a314_Buffer);
461 ior->a314_Request.io_Error = A314_WRITE_OK;
462 ReplyMsg((struct Message *)ior);
466 s->pending_write = ior;
467 add_to_send_queue(s, len);
473 static void handle_app_eos(struct A314_IORequest *ior, struct Socket *s)
475 debug_printf("Received an EOS request from application\n");
477 if (s == NULL || (s->flags & SOCKET_CLOSED))
479 ior->a314_Request.io_Error = A314_EOS_RESET;
480 ReplyMsg((struct Message *)ior);
484 if (s->pending_connect != NULL || s->pending_write != NULL || (s->flags & SOCKET_RCVD_EOS_FROM_APP))
486 ior->a314_Length = 0;
487 ior->a314_Request.io_Error = A314_EOS_RESET;
488 ReplyMsg((struct Message *)ior);
490 close_socket(s, TRUE);
494 s->flags |= SOCKET_RCVD_EOS_FROM_APP;
496 if (send_queue_head == NULL && room_in_a2r(0))
498 append_a2r_packet(PKT_EOS, s->stream_id, 0, NULL);
500 ior->a314_Request.io_Error = A314_EOS_OK;
501 ReplyMsg((struct Message *)ior);
503 s->flags |= SOCKET_SENT_EOS_TO_RPI;
505 if (s->flags & SOCKET_SENT_EOS_TO_APP)
506 close_socket(s, FALSE);
510 s->pending_write = ior;
511 add_to_send_queue(s, 0);
517 static void handle_app_reset(struct A314_IORequest *ior, struct Socket *s)
519 debug_printf("Received a RESET request from application\n");
521 if (s == NULL || (s->flags & SOCKET_CLOSED))
523 ior->a314_Request.io_Error = A314_RESET_OK;
524 ReplyMsg((struct Message *)ior);
528 ior->a314_Request.io_Error = A314_RESET_OK;
529 ReplyMsg((struct Message *)ior);
531 close_socket(s, TRUE);
535 static void handle_app_request(struct A314_IORequest *ior)
537 struct Socket *s = find_socket(ior->a314_Request.io_Message.mn_ReplyPort->mp_SigTask, ior->a314_Socket);
539 switch (ior->a314_Request.io_Command)
542 handle_app_connect(ior, s);
545 handle_app_read(ior, s);
548 handle_app_write(ior, s);
551 handle_app_eos(ior, s);
554 handle_app_reset(ior, s);
557 ior->a314_Request.io_Error = IOERR_NOCMD;
558 ReplyMsg((struct Message *)ior);
567 debug_printf("Waiting for signal\n");
569 ULONG signal = Wait(SIGF_MSGPORT | SIGF_INT);
571 UBYTE prev_a2r_tail = ca->a2r_tail;
572 UBYTE prev_r2a_head = ca->r2a_head;
574 if (signal & SIGF_MSGPORT)
579 while (msg = GetMsg(&task_mp))
580 handle_app_request((struct A314_IORequest *)msg);
584 while (a_enable == 0)
586 handle_packets_received_r2a();
587 handle_room_in_a2r();
590 if (ca->a2r_tail != prev_a2r_tail)
591 r_events |= R_EVENT_A2R_TAIL;
592 if (ca->r2a_head != prev_r2a_head)
593 r_events |= R_EVENT_R2A_HEAD;
595 UBYTE discard_value = ca->a_events;
597 if (ca->r2a_head == ca->r2a_tail)
599 if (send_queue_head == NULL)
600 a_enable = A_EVENT_R2A_TAIL;
601 else if (!room_in_a2r(send_queue_head->send_queue_required_length))
602 a_enable = A_EVENT_R2A_TAIL | A_EVENT_A2R_HEAD;
606 ca->a_enable = a_enable;
608 ca->r_events = r_events;
614 // There is currently no way to unload a314.device.
616 //debug_printf("Shutting down\n");
618 //RemIntServer(INTB_PORTS, &ports_interrupt);
619 //RemIntServer(INTB_VERTB, &vertb_interrupt);
620 //FreeMem(ca, sizeof(struct ComArea));
622 // Stack and task structure should be reclaimed.