Val _lib7_Sock_getpeername (Task* task, Val arg) { //====================== // // Mythryl type: Socket -> (Address_Family, Address) // // This function gets bound as get_peer_name' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); char addr[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int sockfd = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, NULL ); // int status = getpeername (sockfd, (struct sockaddr *)addr, &address_len); // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (status < 0) return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); Val cdata = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, addr, address_len, NULL ); Val result = make_vector_header(task, UNT8_RO_VECTOR_TAGWORD, cdata, address_len); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }
Val _lib7_Sock_inetany (Task* task, Val arg) { //================== // // Mythryl type: Int -> Internet_Address // // Make an INET_ANY INET socket address, with the given port ID. // // This fn gets bound as inet_any in: // // src/lib/std/src/socket/internet-socket.pkg // ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_inetany"); struct sockaddr_in addr; memset( &addr, 0, sizeof(struct sockaddr_in) ); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl( INADDR_ANY ); addr.sin_port = htons( TAGGED_INT_TO_C_INT( arg ) ); // Last use of 'arg'. Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, &addr, sizeof(struct sockaddr_in), NULL ); return make_vector_header(task, UNT8_RO_VECTOR_TAGWORD, data, sizeof(struct sockaddr_in) ); }
Val _lib7_Sock_accept (Task* task, Val arg) { //================= // // Mythryl type: Socket -> (Socket, Address) // // This fn gets bound as accept' in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_accept"); int socket = TAGGED_INT_TO_C_INT( arg ); // Last use of 'arg'. char address_buf[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int new_socket; RELEASE_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_accept", NULL ); // /* do { */ /* Backed out 2010-02-26 CrT: See discussion at bottom of src/c/lib/socket/connect.c */ new_socket = accept (socket, (struct sockaddr*) address_buf, &address_len); /* } while (new_socket < 0 && errno == EINTR); */ /* Restart if interrupted by a SIGALRM or SIGCHLD or whatever. */ // RECOVER_MYTHRYL_HEAP( task->pthread, "_lib7_Sock_accept" ); if (new_socket == -1) { // return RAISE_SYSERR__MAY_HEAPCLEAN( task, new_socket, NULL); // } else { // Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, address_buf, address_len, NULL ); Val address = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, address_len); return make_two_slot_record(task, TAGGED_INT_FROM_C_INT( new_socket ), address); } }
Val _lib7_Sock_frominetaddr (Task* task, Val arg) { //======================= // // Mythryl type: Internet_Address -> (Internet_Address, Int) // // Given a INET-domain socket address, return the INET address and port number. // // This fn gets bound as from_inet_addr in: // // src/lib/std/src/socket/internet-socket.pkg ENTER_MYTHRYL_CALLABLE_C_FN("_lib7_Sock_frominetaddr"); struct sockaddr_in* addr = GET_VECTOR_DATACHUNK_AS( struct sockaddr_in*, arg ); // Last use of 'arg'. ASSERT( addr->sin_family == AF_INET ); Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, &(addr->sin_addr), sizeof(struct in_addr), NULL ); Val inAddr = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, sizeof(struct in_addr) ); return make_two_slot_record(task, inAddr, TAGGED_INT_FROM_C_INT(ntohs(addr->sin_port)) ); }
Val _lib7_Sock_recvbuffrom (Task* task, Val arg) { //====================== // // Mythryl type: (Socket, rw_vector_of_one_byte_unts::Rw_Vector, Int, Int, Bool, Bool) -> (Int, Addr) // // The arguments are: // socket, // data buffer, // start position, // number of bytes, // OOB flag // peek flag. // // The result is: // number of bytes read // source address. // // This fn gets bound as recv_from_a in: // // src/lib/std/src/socket/socket-guts.pkg ENTER_MYTHRYL_CALLABLE_C_FN(__func__); char address_buf[ MAX_SOCK_ADDR_BYTESIZE ]; socklen_t address_len = MAX_SOCK_ADDR_BYTESIZE; int socket = GET_TUPLE_SLOT_AS_INT( arg, 0); // Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); // Mythryl buffer to read bytes into. // We'll fetch this after the call, since it may move around during the call. int offset = GET_TUPLE_SLOT_AS_INT( arg, 2); // Offset within buf to read bytes into. int nbytes = GET_TUPLE_SLOT_AS_INT( arg, 3); // Number of bytes to read. int flag = 0; int n; if (GET_TUPLE_SLOT_AS_VAL(arg, 4) == HEAP_TRUE) flag |= MSG_OOB; if (GET_TUPLE_SLOT_AS_VAL(arg, 5) == HEAP_TRUE) flag |= MSG_PEEK; // We cannot reference anything on the Mythryl heap // between RELEASE_MYTHRYL_HEAP and RECOVER_MYTHRYL_HEAP // because garbage collection might be moving // it around, so allocate a C-side read buffer: // Mythryl_Heap_Value_Buffer readbuf_buf; // { char* c_readbuf = buffer_mythryl_heap_nonvalue( &readbuf_buf, nbytes ); RELEASE_MYTHRYL_HEAP( task->hostthread, __func__, &arg ); // 'arg' is still live here! // do { // n = recvfrom( socket, c_readbuf, nbytes, flag, (struct sockaddr *)address_buf, &address_len ); } while (n < 0 && errno == EINTR); // Restart if interrupted by a SIGALRM or SIGCHLD or whatever. // RECOVER_MYTHRYL_HEAP( task->hostthread, __func__ ); if (n < 0) { unbuffer_mythryl_heap_value( &readbuf_buf ); return RAISE_SYSERR__MAY_HEAPCLEAN(task, status, NULL); } Val buf = GET_TUPLE_SLOT_AS_VAL( arg, 1); // Mythryl buffer to read bytes into. char* bufstart = HEAP_STRING_AS_C_STRING(buf) + offset; memcpy( bufstart, c_readbuf, n); unbuffer_mythryl_heap_value( &readbuf_buf ); } Val data = make_biwordslots_vector_sized_in_bytes__may_heapclean( task, address_buf, address_len, NULL ); Val address = make_vector_header( task, UNT8_RO_VECTOR_TAGWORD, data, address_len); Val result = make_two_slot_record(task, TAGGED_INT_FROM_C_INT(n), address); EXIT_MYTHRYL_CALLABLE_C_FN(__func__); return result; }