Disruption_Kind :: enum_flags { NONE; CONNECT; SEND; CANCEL; } Disruption :: struct { delay: s32; kind: Disruption_Kind; } socket_dispatch :: (args: Args, is_set: Is_Set) { disruption := disruption_make(args, is_set); code_connect :: #code { disruption_dispatch(disruption, .CONNECT); }; code_send :: #code { disruption_dispatch(disruption, .SEND); }; socket_send_message( "Hello from Jai!\n", disruption, code_connect, code_send ); } test__socket_send_message :: #procedure_of_call socket_send_message("A"); #scope_file #import "Socket"; #import "POSIX"; TIMEOUT_SEC :: 2; NO_YAP :: true; yap :: inline (msg: string, args: ..Any) { #if !NO_YAP then log(msg, ..args); } socket_send_message :: inline (message: string) { socket_send_message(message, {}, #code {}, #code {}); } socket_send_message :: ( message: string, disruption: Disruption, $code_connect: Code, $code_send: Code ) { socket_init(); tv := timeval.{ tv_sec = TIMEOUT_SEC, tv_usec = 0 }; sock := socket(AF_INET, .STREAM, 0); defer close_and_reset(*sock); assert(sock > 0, "Socket"); server_addr: sockaddr_in; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr(HOST); setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, *tv, size_of(type_of(tv))); setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, *tv, size_of(type_of(tv))); result := connect(sock, cast(*sockaddr, *server_addr), size_of(type_of(server_addr))); if result != 0 { log_error("No connection"); return; } #insert,scope() code_connect; yap("Connected to %:%", HOST, PORT); bytes_sent := send(sock, message.data, xx message.count, 0); assert(bytes_sent >= 0, "Failed to send message"); #insert,scope() code_send; yap("Sent % bytes\n", bytes_sent); buffer: [1024] u8; bytes_received := recv(sock, buffer.data, buffer.count, 0); if bytes_received > 0 { response := string.{ xx bytes_received, buffer.data }; print("Server response: %\n", response); } } disruption_make :: (args: Args, is_set: Is_Set) -> Disruption { d: Disruption; d.delay = args.delay; if is_set.connect then d.kind |= .CONNECT; if is_set.send then d.kind |= .SEND; if is_set.cancel then d.kind |= .CANCEL; return d; } disruption_dispatch :: (d: Disruption, $post_what: Disruption_Kind) #expand { if (d.kind & post_what == 0) return; yap("-- Mode: % ------------", post_what); if (d.delay > 0) then yap("Sleeping for % ms", d.delay); sleep_milliseconds(d.delay); if d.kind & .CANCEL != 0 { yap("Early return"); `return; } }