001 // vim: set ft=cpp: 002 003 include "::/Doc/Comm" 004 005 #define CMD_SOCKET 1 006 #define CMD_CLOSE 2 007 #define CMD_CONNECT_TCP 3 008 #define CMD_SEND 4 009 #define CMD_RECV 5 010 #define CMD_HELLO 0xAA 011 012 #define SOCK_STREAM 1 013 #define SOCK_DGRAM 2 014 #define SOCK_RAW 3 015 016 #define AF_UNSPEC 0 017 #define AF_INET 2 018 #define AF_INET6 10 019 020 #define SNAIL_COM 3 021 #define SNAIL_TIMEOUT 500 022 #define SNAIL_FRAME_SIZE 112 023 024 static CComm* snail_comm; 025 026 static U8 ReadByte() { 027 U8 chr; 028 while (1) { 029 if (FifoU8Rem(snail_comm->RX_fifo, &chr)) 030 return chr; 031 else 032 Yield; 033 } 034 } 035 036 static I8 ReadI8() { 037 I8 chr; 038 while (1) { 039 if (FifoU8Rem(snail_comm->RX_fifo, &chr)) 040 return chr; 041 else 042 Yield; 043 } 044 } 045 046 static U0 ReadBlock(U8* buf, I64 count) { 047 while (count) { 048 if (FifoU8Rem(snail_comm->RX_fifo, buf)) { 049 buf++; 050 count--; 051 } 052 else Yield; 053 } 054 } 055 056 I64 SocketInit() { 057 U8 chr; 058 059 snail_comm = CommInit8n1(SNAIL_COM, 115200); 060 while (FifoU8Rem(snail_comm->RX_fifo, &chr)) {} 061 062 CommPutChar(SNAIL_COM, CMD_HELLO); 063 064 I64 max_time = cnts.jiffies + SNAIL_TIMEOUT * JIFFY_FREQ / 1000; 065 066 do { 067 if (FifoU8Rem(snail_comm->RX_fifo, &chr)) { 068 if (chr == CMD_HELLO) { 069 return 0; 070 } 071 else { 072 "Failed to initialize Snail -- wrong hello 0x%02X\n", chr; 073 "Are you using the right version of snail.py?\n"; 074 throw; 075 } 076 return chr; 077 } 078 else 079 Yield; 080 } 081 while (cnts.jiffies < max_time); 082 083 "Failed to initialize Snail -- make sure COM%d " 084 "is properly configured & snail.py is running!\n", SNAIL_COM; 085 throw; 086 } 087 088 I64 socket(I64 domain, I64 type) { 089 CommPutChar(SNAIL_COM, CMD_SOCKET); 090 CommPutChar(SNAIL_COM, domain); 091 CommPutChar(SNAIL_COM, type); 092 return ReadI8(); 093 } 094 095 I64 close(I64 sockfd) { 096 CommPutChar(SNAIL_COM, CMD_CLOSE); 097 CommPutChar(SNAIL_COM, sockfd); 098 return ReadI8(); 099 } 100 101 I64 create_connection(U8* addr, U16 port) { 102 I64 sockfd = socket(AF_INET, SOCK_STREAM); 103 104 if (sockfd < 0) 105 return sockfd; 106 107 CommPutChar(SNAIL_COM, CMD_CONNECT_TCP); 108 CommPutChar(SNAIL_COM, sockfd); 109 CommPutChar(SNAIL_COM, StrLen(addr)); 110 CommPutS(SNAIL_COM, addr); 111 CommPutChar(SNAIL_COM, port & 0xff); 112 CommPutChar(SNAIL_COM, port >> 8); 113 114 I64 error = ReadI8(); 115 if (error < 0) { 116 close(sockfd); 117 return error; 118 } 119 120 return sockfd; 121 } 122 123 I64 recv(I64 sockfd, U8* buf, I64 len, I64 flags) { 124 // This will be problematic for UDP 125 if (len > SNAIL_FRAME_SIZE) 126 len = SNAIL_FRAME_SIZE; 127 128 CommPutChar(SNAIL_COM, CMD_RECV); 129 CommPutChar(SNAIL_COM, sockfd); 130 CommPutChar(SNAIL_COM, len); 131 CommPutChar(SNAIL_COM, flags); 132 I64 got = ReadI8(); 133 134 if (got > 0) 135 ReadBlock(buf, got); 136 137 return got; 138 } 139 140 I64 send(I64 sockfd, U8* buf, I64 len, I64 flags) { 141 // FIXME: use frames 142 CommPutChar(SNAIL_COM, CMD_SEND); 143 CommPutChar(SNAIL_COM, sockfd); 144 CommPutChar(SNAIL_COM, len); 145 CommPutChar(SNAIL_COM, flags); 146 CommPutBlk(SNAIL_COM, buf, len); 147 return ReadI8(); 148 }