/* // Full copyright information is available in the file ../doc/CREDITS */ #include "defs.h" #include <string.h> #include "execute.h" #include "net.h" #include "util.h" #include "cache.h" /* // ----------------------------------------------------------------- // // If the current object has a connection, it will reassign that // connection too the specified object. // */ void func_reassign_connection(void) { cData * args; Conn * c; Obj * obj; /* Accept a objnum. */ if (!func_init_1(&args, OBJNUM)) return; c = find_connection(cur_frame->object); if (c) { obj = cache_retrieve(args[0].u.objnum); if (!obj) THROW((objnf_id, "Object #%l does not exist.", args[0].u.objnum)) else if (find_connection(obj)) { cthrow(perm_id, "Object %O already has a connection.", obj->objnum); cache_discard(obj); return; } c->objnum = obj->objnum; cache_discard(obj); cur_frame->object->conn = NULL; pop(1); push_int(1); } else { pop(1); push_int(0); } } /* // ----------------------------------------------------------------- */ void func_bind_port(void) { cData * args; Int argc; Int port; char * addr; /* Accept a port to bind to, and a objnum to handle connections. */ if (!func_init_1_or_2(&args, &argc, INTEGER, STRING)) return; addr = (argc==2 ? string_chars(STR2) : (char *) NULL); port=INT1; if (((port >= 0) ? tcp_server(port, addr, cur_frame->object->objnum) : udp_server(-port, addr, cur_frame->object->objnum))) { pop(argc); push_int(1); } else if (server_failure_reason == address_id) THROW((address_id, "Invalid bind address: %s", addr)) else if (server_failure_reason == socket_id) THROW((socket_id, "Couldn't create server socket.")) else if (server_failure_reason == preaddr_id) THROW((preaddr_id, "Couldn't bind to port %d: prebound address conflict", INT1)) else if (server_failure_reason == pretype_id) { if (port > 0) THROW((pretype_id, "Couldn't bind to TCP port %d: already prebound as UDP", INT1)) else THROW((pretype_id, "Couldn't bind to UDP port %d: already prebound as TCP", INT1)) } else if (addr) THROW((server_failure_reason, "Couldn't bind to port %d on address %s", INT1, addr)) else THROW((server_failure_reason, "Couldn't bind to port %d.", INT1)) } /* // ----------------------------------------------------------------- */ void func_unbind_port(void) { cData * args; /* Accept a port number. */ if (!func_init_1(&args, INTEGER)) return; if (!remove_server(args[0].u.val)) THROW((servnf_id, "No server socket on port %d.", args[0].u.val)) else { pop(1); push_int(1); } } /* // ----------------------------------------------------------------- */ void func_open_connection(void) { cData *args; char *address; Int port, argc; Long r; if (!func_init_2_or_3(&args, &argc, STRING, INTEGER, INTEGER)) return; address = string_chars(args[0].u.str); port = args[1].u.val; if (argc==2) r = make_connection(address, port, cur_frame->object->objnum); else r = make_udp_connection(address, port, cur_frame->object->objnum); if (r == address_id) THROW((address_id, "Invalid address")) else if (r == socket_id) THROW((socket_id, "Couldn't create socket for connection")) pop(argc); push_int(1); } /* // ----------------------------------------------------------------- */ void func_close_connection(void) { /* Accept no arguments. */ if (!func_init_0()) return; /* Kick off anyone assigned to the current object. */ push_int(boot(cur_frame->object)); } /* // ----------------------------------------------------------------- // Echo a buffer to the connection */ void func_cwrite(void) { cData *args; int rval; /* Accept a buffer to write. */ if (!func_init_1(&args, BUFFER)) return; /* Write the string to any connection associated with this object. */ rval = tell(cur_frame->object, args[0].u.buffer) ? 1 : 0; pop(1); push_int(rval); } /* // ----------------------------------------------------------------- // write a file to the connection */ void func_cwritef(void) { size_t block, r; cData * args; FILE * fp; cBuf * buf; cStr * str; struct stat statbuf; Int nargs; /* Accept the name of a file to echo */ if (!func_init_1_or_2(&args, &nargs, STRING, INTEGER)) return; /* Initialize the file */ str = build_path(args[0].u.str->s, &statbuf, DISALLOW_DIR); if (str == NULL) return; /* Open the file for reading. */ fp = open_scratch_file(str->s, "rb"); if (!fp) THROW((file_id, "Cannot open file \"%s\" for reading.", str->s)) /* how big of a chunk do we read at a time? */ if (nargs == 2) { if (args[1].u.val == -1) block = statbuf.st_size; else block = (size_t) args[1].u.val; } else block = (size_t) DEF_BLOCKSIZE; /* Allocate a buffer to hold the block */ buf = buffer_new(block); while (!feof(fp)) { r = fread(buf->s, sizeof(unsigned char), block, fp); if (r != block) { if (!feof(fp)) { buffer_discard(buf); close_scratch_file(fp); cthrow(file_id, "Trouble reading file \"%s\": %s", str->s, strerror(GETERR())); return; } else { buf->len = r; tell(cur_frame->object, buf); } } else tell(cur_frame->object, buf); } /* Discard the buffer and close the file. */ buffer_discard(buf); close_scratch_file(fp); pop(nargs); push_int((cNum) statbuf.st_size); } /* // ----------------------------------------------------------------- // return random info on the connection */ void func_connection(void) { cList * info; cData * list; Conn * c; if (!func_init_0()) return; c = find_connection(cur_frame->object); if (!c) THROW((net_id, "No connection established.")) info = list_new(4); list = list_empty_spaces(info, 4); list[0].type = INTEGER; list[0].u.val = (cNum) (c->flags.readable ? 1 : 0); list[1].type = INTEGER; list[1].u.val = (cNum) (c->flags.writable ? 1 : 0); list[2].type = INTEGER; list[2].u.val = (cNum) (c->flags.dead ? 1 : 0); list[3].type = INTEGER; list[3].u.val = (cNum) (c->fd); push_list(info); list_discard(info); }