From 884c8093d63402a1ad0b502244b791e3c6782be3 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Fri, 11 Sep 2020 14:38:47 +0900 Subject: Added debian extra dependency packages. Signed-off-by: Michele Calgaro --- debian/transcode/transcode-1.1.7/src/socket.c | 881 ++++++++++++++++++++++++++ 1 file changed, 881 insertions(+) create mode 100644 debian/transcode/transcode-1.1.7/src/socket.c (limited to 'debian/transcode/transcode-1.1.7/src/socket.c') diff --git a/debian/transcode/transcode-1.1.7/src/socket.c b/debian/transcode/transcode-1.1.7/src/socket.c new file mode 100644 index 00000000..5cf1d7e8 --- /dev/null +++ b/debian/transcode/transcode-1.1.7/src/socket.c @@ -0,0 +1,881 @@ +/* socket.c -- routines for controlling transcode over a socket + * Written by Andrew Church + * + * This file is part of transcode, a video stream processing tool. + * transcode is free software, distributable under the terms of the GNU + * General Public License (version 2 or later). See the file COPYING + * for details. + */ + +#include "transcode.h" +#include "encoder.h" +#include "filter.h" +#include "socket.h" +#include "libtc/libtc.h" + +#ifdef HAVE_SYS_SELECT_H +# include +#endif +#include +#include +#include +#include +#include + +/*************************************************************************/ + +/* Pathname for listener socket */ +static char socket_path[PATH_MAX+1] = ""; +/* Socket descriptors for listener socket and client socket */ +static int server_sock = -1; +static int client_sock = -1; + +/* For communicating with "pv" module (FIXME: should go away) */ +pthread_mutex_t tc_socket_msg_lock = PTHREAD_MUTEX_INITIALIZER; +enum tc_socket_msg_cmd_enum tc_socket_msg_cmd; +int tc_socket_msg_arg = 0; + +/*************************************************************************/ +/*************************************************************************/ + +/** + * sendall: Send data to a client_sock, handling partial writes transparently. + * + * Parameters: + * sock: Socket descriptor. + * buf: Data to write. + * count: Number of bytes to send. + * Return value: + * Total number of bytes sent; -1 indicates that the send failed. + */ + +static int sendall(int sock, const void *buf, size_t count) +{ + int total_sent = 0; + + if (sock < 0 || !buf || count < 0) { + tc_log_warn(__FILE__, "sendall(): invalid parameters!"); + errno = EINVAL; + return -1; + } + while (count > 0) { + int retval = send(sock, buf, count, 0); + if (retval <= 0) { + tc_log_warn(__FILE__, "sendall(): socket write failed (%s)", + retval<0 ? strerror(errno) : "Connection closed"); + if (total_sent == 0) + return -1; /* Nothing sent yet, abort with error return */ + break; + } + total_sent += retval; + buf = (int8_t *)buf + retval; + count -= retval; + } + return total_sent; +} + +/*************************************************************************/ + +/** + * sendstr: Send a string to a client_sock, handling partial writes transparently. + * + * Parameters: + * sock: Socket descriptor. + * str: String to write. + * Return value: + * Total number of bytes sent; -1 indicates that the send failed. + */ + +static int sendstr(int sock, const char *str) +{ + return sendall(sock, str, strlen(str)); +} + +/*************************************************************************/ + +/** + * dump_vob: Send the contents of the global `vob' structure over the + * socket in a "parameter=value" format, one field per line. + * + * Parameters: + * sock: Socket descriptor to send data to. + * Return value: + * None. + */ + +static void dump_vob(int sock) +{ + vob_t *vob = tc_get_vob(); + char buf[1000]; + int n; + +#define SEND(field,fmt) \ + n = tc_snprintf(buf, sizeof(buf), "%s=" fmt "\n", #field, vob->field); \ + if (n > 0) \ + sendall(sock, buf, n); + + /* Generated via find-and-replace from vob_t definition in transcode.h */ + SEND(vmod_probed, "%s"); + SEND(amod_probed, "%s"); + SEND(vmod_probed_xml, "%s"); + SEND(amod_probed_xml, "%s"); + SEND(verbose, "%d"); + SEND(video_in_file, "%s"); + SEND(audio_in_file, "%s"); + SEND(nav_seek_file, "%s"); + SEND(has_audio, "%d"); + SEND(has_audio_track, "%d"); + SEND(has_video, "%d"); + SEND(lang_code, "%d"); + SEND(a_track, "%d"); + SEND(v_track, "%d"); + SEND(s_track, "%d"); + SEND(sync, "%d"); + SEND(sync_ms, "%d"); + SEND(dvd_title, "%d"); + SEND(dvd_chapter1, "%d"); + SEND(dvd_chapter2, "%d"); + SEND(dvd_max_chapters, "%d"); + SEND(dvd_angle, "%d"); + SEND(ps_unit, "%d"); + SEND(ps_seq1, "%d"); + SEND(ps_seq2, "%d"); + SEND(ts_pid1, "%d"); + SEND(ts_pid2, "%d"); + SEND(vob_offset, "%d"); + SEND(vob_chunk, "%d"); + SEND(vob_chunk_num1, "%d"); + SEND(vob_chunk_num2, "%d"); + SEND(vob_chunk_max, "%d"); + SEND(vob_percentage, "%d"); + SEND(vob_psu_num1, "%d"); + SEND(vob_psu_num2, "%d"); + SEND(vob_info_file, "%s"); + SEND(pts_start, "%f"); + SEND(psu_offset, "%f"); + SEND(demuxer, "%d"); + SEND(v_format_flag, "%ld"); + SEND(v_codec_flag, "%ld"); + SEND(a_format_flag, "%ld"); + SEND(a_codec_flag, "%ld"); + SEND(quality, "%d"); + SEND(a_stream_bitrate, "%d"); + SEND(a_chan, "%d"); + SEND(a_bits, "%d"); + SEND(a_rate, "%d"); + SEND(a_padrate, "%d"); + SEND(im_a_size, "%d"); + SEND(ex_a_size, "%d"); + SEND(im_a_codec, "%d"); + SEND(a_leap_frame, "%d"); + SEND(a_leap_bytes, "%d"); + SEND(a_vbr, "%d"); + SEND(a52_mode, "%d"); + SEND(dm_bits, "%d"); + SEND(dm_chan, "%d"); + SEND(v_stream_bitrate, "%d"); + SEND(fps, "%f"); + SEND(im_frc, "%d"); + SEND(ex_fps, "%f"); + SEND(ex_frc, "%d"); + SEND(hard_fps_flag, "%d"); + SEND(pulldown, "%d"); + SEND(im_v_height, "%d"); + SEND(im_v_width, "%d"); + SEND(im_v_size, "%d"); + SEND(im_asr, "%d"); + SEND(im_par, "%d"); + SEND(im_par_width, "%d"); + SEND(im_par_height, "%d"); + SEND(ex_asr, "%d"); + SEND(ex_par, "%d"); + SEND(ex_par_width, "%d"); + SEND(ex_par_height, "%d"); + SEND(attributes, "%d"); + SEND(im_v_codec, "%d"); + SEND(encode_fields, "%d"); + SEND(dv_yuy2_mode, "%d"); + SEND(volume, "%f"); + SEND(ac3_gain[0], "%f"); + SEND(ac3_gain[1], "%f"); + SEND(ac3_gain[2], "%f"); + SEND(clip_count, "%d"); + SEND(ex_v_width, "%d"); + SEND(ex_v_height, "%d"); + SEND(ex_v_size, "%d"); + SEND(reduce_h, "%d"); + SEND(reduce_w, "%d"); + SEND(resize1_mult, "%d"); + SEND(vert_resize1, "%d"); + SEND(hori_resize1, "%d"); + SEND(resize2_mult, "%d"); + SEND(vert_resize2, "%d"); + SEND(hori_resize2, "%d"); + SEND(zoom_width, "%d"); + SEND(zoom_height, "%d"); + SEND(zoom_interlaced, "%d"); + SEND(zoom_filter, "%d"); + SEND(antialias, "%d"); + SEND(deinterlace, "%d"); + SEND(decolor, "%d"); + SEND(aa_weight, "%f"); + SEND(aa_bias, "%f"); + SEND(gamma, "%f"); + SEND(ex_clip_top, "%d"); + SEND(ex_clip_bottom, "%d"); + SEND(ex_clip_left, "%d"); + SEND(ex_clip_right, "%d"); + SEND(im_clip_top, "%d"); + SEND(im_clip_bottom, "%d"); + SEND(im_clip_left, "%d"); + SEND(im_clip_right, "%d"); + SEND(post_ex_clip_top, "%d"); + SEND(post_ex_clip_bottom, "%d"); + SEND(post_ex_clip_left, "%d"); + SEND(post_ex_clip_right, "%d"); + SEND(pre_im_clip_top, "%d"); + SEND(pre_im_clip_bottom, "%d"); + SEND(pre_im_clip_left, "%d"); + SEND(pre_im_clip_right, "%d"); + SEND(video_out_file, "%s"); + SEND(audio_out_file, "%s"); + SEND(avifile_in, "%p"); // not sure if there's any point sending these... + SEND(avifile_out, "%p"); + SEND(avi_comment_fd, "%d"); + SEND(audio_file_flag, "%d"); + SEND(divxbitrate, "%d"); + SEND(divxkeyframes, "%d"); + SEND(divxquality, "%d"); + SEND(divxcrispness, "%d"); + SEND(divxmultipass, "%d"); + SEND(video_max_bitrate, "%d"); + SEND(divxlogfile, "%s"); + SEND(min_quantizer, "%d"); + SEND(max_quantizer, "%d"); + SEND(rc_period, "%d"); + SEND(rc_reaction_period, "%d"); + SEND(rc_reaction_ratio, "%d"); + SEND(divx5_vbv_prof, "%d"); + SEND(divx5_vbv_bitrate, "%d"); + SEND(divx5_vbv_size, "%d"); + SEND(divx5_vbv_occupancy, "%d"); + SEND(mp3bitrate, "%d"); + SEND(mp3frequency, "%d"); + SEND(mp3quality, "%f"); + SEND(mp3mode, "%d"); + SEND(bitreservoir, "%d"); + SEND(lame_preset, "%s"); + SEND(audiologfile, "%s"); + SEND(ex_a_codec, "%d"); + SEND(ex_v_codec, "%d"); + SEND(ex_v_fcc, "%s"); + SEND(ex_a_fcc, "%s"); + SEND(ex_profile_name, "%s"); + SEND(pass_flag, "%d"); + SEND(encoder_flush, "%d"); + SEND(mod_path, "%s"); + SEND(ttime, "%p"); // format this as a -c style string? + SEND(frame_interval, "%u"); + SEND(im_v_string, "%s"); + SEND(im_a_string, "%s"); + SEND(ex_v_string, "%s"); + SEND(ex_a_string, "%s"); + SEND(ex_m_string, "%s"); + SEND(m2v_requant, "%f"); + SEND(mpeg_profile, "%d"); + SEND(export_attributes, "%u"); + +#undef SEND +} + +/*************************************************************************/ +/*************************************************************************/ + +/* Socket actions. */ + +/*************************************************************************/ + +/** + * handle_config(): Process a "config" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_config(char *params) +{ + char *filter_name, *filter_params; + int filter_id; + + filter_name = params; + filter_params = filter_name + strcspn(filter_name, " \t"); + *filter_params++ = 0; + filter_params += strspn(filter_params, " \t"); + if (!*filter_name || !*filter_params) + return 0; + + filter_id = tc_filter_find(filter_name); + if (!filter_id) + return 0; + else + return tc_filter_configure(filter_id, filter_params) == 0; +} + +/*************************************************************************/ + +/** + * handle_disable(): Process a "disable" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_disable(char *params) +{ + int filter_id; + + filter_id = tc_filter_find(params); + if (!filter_id) + return 0; + else + return tc_filter_disable(filter_id); +} + +/*************************************************************************/ + +/** + * handle_enable(): Process an "enable" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_enable(char *params) +{ + int filter_id; + + filter_id = tc_filter_find(params); + if (!filter_id) + return 0; + else + return tc_filter_enable(filter_id); +} + +/*************************************************************************/ + +/** + * handle_help(): Process a "help" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_help(char *params) +{ + sendstr(client_sock, + "load \n" + "unload \n" + "enable \n" + "disable \n" + "config \n" + "parameters \n" + "list [ load | enable | disable ]\n" + "dump\n" + "progress\n" + "pause\n" + "preview \n" + " [ draw | undo | pause | fastfw |\n" + " slowfw | slowbw | rotate |\n" + " rotate | display | slower |\n" + " faster | toggle | grab ]\n" + "help\n" + "version\n" + "quit\n" + ); + return 1; +} + +/*************************************************************************/ + +/** + * handle_list(): Process a "list" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_list(char *params) +{ + const char *list = NULL; + + if (strncasecmp(params, "load", 2) == 0) + list = tc_filter_list(TC_FILTER_LIST_LOADED); + else if (strncasecmp(params, "enable", 2) == 0) + list = tc_filter_list(TC_FILTER_LIST_ENABLED); + else if (strncasecmp(params, "disable", 2) == 0) + list = tc_filter_list(TC_FILTER_LIST_DISABLED); + + if (list) { + sendstr(client_sock, list); + return 1; + } else { + return 0; + } +} + +/*************************************************************************/ + +/** + * handle_load(): Process a "load" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_load(char *params) +{ + char *name, *options; + + name = params; + options = strchr(params, ' '); + if (options) { + *options++ = 0; + options += strspn(options, " \t"); + } + return tc_filter_add(name, options); +} + +/*************************************************************************/ + +/** + * handle_parameter(): Process a "parameter" command received on the + * socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_parameter(char *params) +{ + int filter_id; + const char *s; + + filter_id = tc_filter_find(params); + if (!filter_id) + return 0; + s = tc_filter_get_conf(filter_id, NULL); + if (!s) + return 0; + sendstr(client_sock, s); + return 1; +} + +/*************************************************************************/ + +/** + * handle_preview(): Process a "preview" command received on the socket. + * + * Parameters: + * params: Command parameters. + * Return value: + * Nonzero on success, zero on failure. + */ + +static int handle_preview(char *params) +{ + int filter_id, cmd, arg; + char *cmdstr, *argstr; + + /* Check that the preview filter is loaded, and load it if not */ + filter_id = tc_filter_find("pv"); + if (!filter_id) { + filter_id = tc_filter_add("pv", "cache=20"); + if (!filter_id) + return 0; + } + + /* Parse out preview command name and (optional) argument */ + cmdstr = strtok(params, " \t"); + if (cmdstr) // there are strtok() implementations that crash without this! + argstr = strtok(NULL, " \t"); + else + argstr = NULL; + if (argstr) + arg = atoi(argstr); + else + arg = 0; + + if (!strncasecmp(cmdstr, "draw", 2)) { + cmd = TC_SOCK_PV_DRAW; + } else if (!strncasecmp(cmdstr, "pause", 2)) { + cmd = TC_SOCK_PV_PAUSE; + } else if (!strncasecmp(cmdstr, "undo", 2)) { + cmd = TC_SOCK_PV_UNDO; + } else if (!strncasecmp(cmdstr, "fastfw", 6)) { + cmd = TC_SOCK_PV_FAST_FW; + } else if (!strncasecmp(cmdstr, "fastbw", 6)) { + cmd = TC_SOCK_PV_FAST_BW; + } else if (!strncasecmp(cmdstr, "slowfw", 6)) { + cmd = TC_SOCK_PV_SLOW_FW; + } else if (!strncasecmp(cmdstr, "slowbw", 6)) { + cmd = TC_SOCK_PV_SLOW_BW; + } else if (!strncasecmp(cmdstr, "toggle", 6)) { + cmd = TC_SOCK_PV_TOGGLE; + } else if (!strncasecmp(cmdstr, "slower", 6)) { + cmd = TC_SOCK_PV_SLOWER; + } else if (!strncasecmp(cmdstr, "faster", 6)) { + cmd = TC_SOCK_PV_FASTER; + } else if (!strncasecmp(cmdstr, "rotate", 6)) { + cmd = TC_SOCK_PV_ROTATE; + } else if (!strncasecmp(cmdstr, "display", 6)) { + cmd = TC_SOCK_PV_DISPLAY; + } else if (!strncasecmp(cmdstr, "grab", 4)) { + cmd = TC_SOCK_PV_SAVE_JPG; + } else { + return 0; + } + + pthread_mutex_lock(&tc_socket_msg_lock); + tc_socket_msg_cmd = cmd; + tc_socket_msg_arg = arg; + pthread_mutex_unlock(&tc_socket_msg_lock); + + return 1; +} + +/*************************************************************************/ + +/** + * handle: Handle a single message from a socket. + * + * Parameters: + * buf: Line read from socket. + * Return value: + * Zero if the socket is to be closed, nonzero otherwise. + */ + +static int handle(char *buf) +{ + char *cmd, *params; + int len, retval; + + len = strlen(buf); + if (len > 0 && buf[len-1] == '\n') + buf[--len] = 0; + if (len > 0 && buf[len-1] == '\r') + buf[--len] = 0; + //tc_log_msg(__FILE__, "read from socket: |%s|", buf); + + cmd = buf + strspn(buf, " \t"); + params = cmd + strcspn(cmd, " \t"); + *params++ = 0; + params += strspn(params, " \t"); + + if (!*cmd) { // not strictly necessary, but lines up else if's nicely + retval = 0; + } else if (strncasecmp(cmd, "config", 2) == 0) { + retval = handle_config(params); + } else if (strncasecmp(cmd, "disable", 2) == 0) { + retval = handle_disable(params); + } else if (strncasecmp(cmd, "dump", 2) == 0) { + dump_vob(client_sock); + retval = 1; + } else if (strncasecmp(cmd, "enable", 2) == 0) { + retval = handle_enable(params); + } else if (strncasecmp(cmd, "help", 2) == 0) { + retval = handle_help(params); + } else if (strncasecmp(cmd, "list", 2) == 0) { + retval = handle_list(params); + } else if (strncasecmp(cmd, "load", 2) == 0) { + retval = handle_load(params); + } else if (strncasecmp(cmd, "parameters", 3) == 0) { + retval = handle_parameter(params); + } else if (strncasecmp(cmd, "pause", 3) == 0) { + tc_pause_request(); + retval = 1; + } else if (strncasecmp(cmd, "preview", 3) == 0) { + retval = handle_preview(params); + } else if (strncasecmp(cmd, "progress", 3) == 0) { + tc_progress_meter = !tc_progress_meter; + retval = 1; + } else if (strncasecmp(cmd, "quit", 2) == 0 + || strncasecmp(cmd, "exit", 2) == 0) { + return 0; // tell caller to close socket + } else if (strncasecmp(cmd, "unload", 2) == 0) { + retval = 0; // FIXME: not implemented + } else if (strncasecmp(cmd, "version", 2) == 0) { + sendstr(client_sock, PACKAGE_VERSION "\n"); + retval = 1; + } else { + retval = 0; + } + + sendstr(client_sock, retval ? "OK\n" : "FAILED\n"); + return 1; // socket remains open +} + +/*************************************************************************/ +/*************************************************************************/ + +/* External interfaces. */ + +/*************************************************************************/ + +/** + * tc_socket_init: Initialize the socket code, and open a listener socket + * with the given pathname. + * + * Parameters: + * socket_path_: Pathname to use for communication socket. + * Return value: + * Nonzero on success, zero on failure. + * Side effects: + * If `socket_path' points to an existing file, the file is removed. + */ + +int tc_socket_init(const char *socket_path_) +{ + struct sockaddr_un server_addr; + + client_sock = -1; + server_sock = -1; + + if (tc_snprintf(socket_path, sizeof(socket_path), "%s", socket_path_) < 0){ + tc_log_error(__FILE__, "Socket pathname too long (1)"); + *socket_path = 0; + return 0; + } + + errno = 0; + if (unlink(socket_path) != 0 && errno != ENOENT) { + tc_log_error(__FILE__, "Unable to remove \"%s\": %s", + socket_path, strerror(errno)); + return 0; + } + + server_addr.sun_family = AF_UNIX; + if (tc_snprintf(server_addr.sun_path, sizeof(server_addr.sun_path), + "%s", socket_path) < 0 + ) { + tc_log_error(__FILE__, "Socket pathname too long"); + return 0; + } + server_sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (server_sock < 0) { + tc_log_perror(__FILE__, "Unable to create server socket"); + return 0; + } + if (bind(server_sock, (struct sockaddr *)&server_addr, + sizeof(server_addr)) + ) { + tc_log_perror(__FILE__, "Unable to bind server socket"); + close(server_sock); + server_sock = -1; + unlink(socket_path); // just in case + return 0; + } + if (listen(server_sock, 5) < 0) { + tc_log_perror(__FILE__, "Unable to activate server socket"); + close(server_sock); + unlink(socket_path); + return 0; + } + + return 1; +} + +/*************************************************************************/ + +/** + * tc_socket_fini: Close the listener and client sockets, if open, and + * perform any other necessary cleanup. + * + * Parameters: + * None. + * Return value: + * None. + */ + +void tc_socket_fini(void) +{ + if (client_sock >= 0) { + close(client_sock); + client_sock = -1; + } + if (server_sock >= 0) { + close(server_sock); + server_sock = -1; + unlink(socket_path); + } +} + +/*************************************************************************/ + +/** + * tc_socket_poll_internal: Check server and (if connected) client sockets for + * pending events, and process them, with tunable timeout. + * + * Parameters: + * blocking: if !0, blocks forever caller until next event. + * if 0, just check once if there is an event to process + * and execute (or just return) immediately. + * Return value: + * None. + * Preconditions: + * valid (!= -1) server socket avalaible. + */ + +static void tc_socket_poll_internal(int blocking) +{ + fd_set rfds, wfds; + char msgbuf[TC_BUF_MAX]; + int maxfd = -1, retval = -1; + struct timeval tv = {0, 0}, *ptv = (blocking) ?NULL :&tv; + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + + FD_SET(server_sock, &rfds); + maxfd = server_sock; + + if (client_sock >= 0) { + FD_SET(client_sock, &rfds); + //FD_SET(client_sock, &wfds); + if (client_sock > maxfd) + maxfd = client_sock; + } + retval = select(maxfd+1, &rfds, &wfds, NULL, ptv); + + if (retval == 0) { + /* nothing interesting happened. It happens :) */ + return; + } + if (retval < 0 && errno != EINTR) { + /* EINTR is an expected "exceptional" condition */ + tc_log_warn(__FILE__, "select(): %s", strerror(errno)); + return; + } + + if (FD_ISSET(server_sock, &rfds)) { + int newsock = accept(server_sock, NULL, 0); + if (newsock < 0) { + tc_log_warn(__FILE__, "Unable to accept new connection: %s", + strerror(errno)); + return; + } + if (client_sock >= 0) { + /* We already have a connection, so drop this one */ + close(newsock); + } else { + client_sock = newsock; + } + } + + if (client_sock >= 0 && FD_ISSET(client_sock, &rfds)) { + retval = recv(client_sock, msgbuf, sizeof(msgbuf)-1, 0); + if (retval <= 0) { + if (retval < 0) + tc_log_perror(__FILE__, "Unable to read message from socket"); + close(client_sock); + client_sock = -1; + } else { + if (retval > sizeof(msgbuf)-1) // paranoia + retval = sizeof(msgbuf)-1; + msgbuf[retval] = 0; + if (!handle(msgbuf)) { + close(client_sock); + client_sock = -1; + } + } + } +} + +/** + * tc_socket_poll: Check server and (if connected) client sockets for + * pending events, and process them. + * This call should never block caller, returnin immediately if there + * isn't any event pending. + * + * Parameters: + * None. + * Return value: + * None. + */ + +void tc_socket_poll(void) +{ + if (server_sock < 0 && client_sock < 0) { + /* Nothing to poll! */ + return; + } + tc_socket_poll_internal(0); +} + +/** + * tc_socket_wait: Wait forever server and (if connected) client sockets + * for next event, and process the next first one and exit. + * This call will always block until next event happens. + * + * Parameters: + * None. + * Return value: + * None. + */ + +void tc_socket_wait(void) +{ + if (server_sock < 0 && client_sock < 0) { + pause(); + /* if no server socket is avalaible (= no tc_socket_init + * called before), nothing will ever happen, so + * we must block forever to satisfy function requirements. + */ + return; + } + tc_socket_poll_internal(1); +} + + +/*************************************************************************/ + +/** + * tc_socket_submit: Send a string to the socket. Does nothing if no + * socket is open. + * + * Parameters: + * str: String to send. + * Return value: + * None. + */ + +void tc_socket_submit(const char *str) +{ + if (socket >= 0) + sendstr(client_sock, str); +} + +/*************************************************************************/ + +/* + * Local variables: + * c-file-style: "stroustrup" + * c-file-offsets: ((case-label . *) (statement-case-intro . *)) + * indent-tabs-mode: nil + * End: + * + * vim: expandtab shiftwidth=4: + */ -- cgit v1.2.3