📄 codec.c
字号:
/* Initialize the codec. */ if (codec->init (data) == SVZ_CODEC_ERROR) { svz_log (LOG_ERROR, "%s: init: %s\n", codec->description, codec->error (data)); svz_codec_sock_recv_revert (sock); return -1; } return 0;}/* This routine is the new @code{check_request} callback for reading codecs. It is applied in the above @code{svz_codec_sock_receive_setup()} function. Usually it gets called whenever there is data in the receive buffer. It lets the current receive buffer be the input of the codec. The output buffer of the codec gets the new receive buffer buffer of the socket structure @var{sock}. The old @code{check_request} callback of @var{sock} gets called afterwards. When leaving this functions the receive buffer gets restored again with the bytes snipped consumed by the codec itself. */intsvz_codec_sock_receive (svz_socket_t *sock){ svz_codec_data_t *data = (svz_codec_data_t *) sock->recv_codec; svz_codec_t *codec = data->codec; int ret; /* Run the encoder / decoder of the applied codec. */ data->flag = SVZ_CODEC_CODE; if (sock->flags & SOCK_FLAG_FLUSH) data->flag = SVZ_CODEC_FINISH; svz_codec_save_recv_buffer (sock, data); while ((ret = codec->code (data)) == SVZ_CODEC_MORE_OUT) { /* Resize output buffer if necessary. */ data->flag = SVZ_CODEC_FLUSH; data->out_size *= 2; data->out_buffer = svz_realloc (data->out_buffer, data->out_size); } /* Evaluate the return value of the codec. */ switch (ret) { case SVZ_CODEC_ERROR: /* Error occurred. */ svz_log (LOG_ERROR, "%s: code: %s\n", codec->description, codec->error (data)); return -1; case SVZ_CODEC_FINISHED: /* Codec finished. */ if (codec->finalize (data) != SVZ_CODEC_OK) { svz_log (LOG_ERROR, "%s: finalize: %s\n", codec->description, codec->error (data)); } break; case SVZ_CODEC_OK: /* No error. */ break; case SVZ_CODEC_MORE_IN: /* Needs more input data to continue. */ break; default: /* Unhandled. */ svz_log (LOG_ERROR, "%s: code: invalid return value: %d\n", codec->description, ret); break; } /* Call the saved @code{check_request} callback with the new receive buffer which is the output buffer of the codec. */ svz_codec_set_recv_buffer (sock, data); if ((ret = data->check_request (sock))) { svz_codec_unset_recv_buffer (sock, data); return ret; } /* Save back changes made to the current receive buffer. */ svz_codec_unset_recv_buffer (sock, data); /* Restore old receive buffer. */ svz_codec_restore_recv_buffer (sock, data); return 0;}/* These are send buffer switcher used to apply the output buffer of a sending codec to the send buffer of a socket structure and vice-versa. */#define svz_codec_set_send_buffer(sock, data) \ do { \ sock->send_buffer = data->out_buffer; \ sock->send_buffer_size = data->out_size; \ sock->send_buffer_fill = data->out_fill; \ } while (0)#define svz_codec_unset_send_buffer(sock, data) \ do { \ data->out_buffer = sock->send_buffer; \ data->out_size = sock->send_buffer_size; \ data->out_fill = sock->send_buffer_fill; \ } while (0)#define svz_codec_save_send_buffer(sock, data) \ do { \ data->in_buffer = sock->send_buffer; \ data->in_fill = sock->send_buffer_fill; \ data->in_size = sock->send_buffer_size; \ } while (0)#define svz_codec_restore_send_buffer(sock, data) \ do { \ sock->send_buffer = data->in_buffer; \ sock->send_buffer_size = data->in_size; \ sock->send_buffer_fill = data->in_fill; \ } while (0)/* Reverts the changes made in @code{svz_codec_sock_send_setup()}. */static voidsvz_codec_sock_send_revert (svz_socket_t *sock){ svz_codec_data_t *data = (svz_codec_data_t *) sock->send_codec; svz_codec_restore_send_buffer (sock, data); sock->check_request = data->check_request; sock->disconnected_socket = data->disconnected_socket; svz_free (data->out_buffer); svz_free (sock->send_codec); sock->send_codec = NULL;}/* Setup the socket structure @var{sock} for encoding or decoding its send buffer via the given codec @var{codec}. Therefore you previously need to assign the @code{write_socket} member of @var{sock} properly. The function returns zero on success, non-zero otherwise. */intsvz_codec_sock_send_setup (svz_socket_t *sock, svz_codec_t *codec){ svz_codec_data_t *data; /* Return here if there is already a codec registered. */ if (sock->send_codec != NULL) return 0; /* Setup internal codec data. */ data = svz_malloc (sizeof (svz_codec_data_t)); data->codec = codec; data->flag = SVZ_CODEC_INIT; data->config = data->data = NULL; sock->send_codec = data; /* Save the given sockets send buffer, the @code{write_socket} callback and the @code{disconnected_socket} callback if necessary. */ svz_codec_save_send_buffer (sock, data); data->write_socket = sock->write_socket; sock->write_socket = svz_codec_sock_send; if (sock->disconnected_socket != svz_codec_sock_disconnect) { data->disconnected_socket = sock->disconnected_socket; sock->disconnected_socket = svz_codec_sock_disconnect; } /* Apply new send buffer which is the output buffer of the codec. */ data->out_fill = 0; data->out_size = sock->send_buffer_size; data->out_buffer = svz_malloc (data->out_size); /* Initialize the codec. */ if (codec->init (data) == SVZ_CODEC_ERROR) { svz_log (LOG_ERROR, "%s: init: %s\n", codec->description, codec->error (data)); svz_codec_sock_send_revert (sock); return -1; } return 0;}/* This is a codec socket structures @var{sock} new @code{write_socket} callback which is called whenever there is data within the send buffer available and @var{sock} is scheduled for writing. It uses the current send buffer as input buffer for the codec. The output buffer of the codec is used to invoke the @code{write_socket} callback saved within @code{svz_codec_sock_send_setup()}. After this the send buffer is restored again without the bytes consumed by the codec. */intsvz_codec_sock_send (svz_socket_t *sock){ svz_codec_data_t *data = (svz_codec_data_t *) sock->send_codec; svz_codec_t *codec = data->codec; int ret; /* Run the encoder / decoder of the applied codec. */ data->flag = SVZ_CODEC_CODE; if (sock->flags & SOCK_FLAG_FLUSH) data->flag = SVZ_CODEC_FINISH; svz_codec_save_send_buffer (sock, data); while ((ret = codec->code (data)) == SVZ_CODEC_MORE_OUT) { /* Resize output buffer if necessary. */ data->flag = SVZ_CODEC_FLUSH; data->out_size *= 2; data->out_buffer = svz_realloc (data->out_buffer, data->out_size); } /* Evaluate the return value of the codec. */ switch (ret) { case SVZ_CODEC_ERROR: /* Error occurred. */ svz_log (LOG_ERROR, "%s: code: %s\n", codec->description, codec->error (data)); return -1; case SVZ_CODEC_FINISHED: /* Codec finished. */ if (codec->finalize (data) != SVZ_CODEC_OK) { svz_log (LOG_ERROR, "%s: finalize: %s\n", codec->description, codec->error (data)); } break; case SVZ_CODEC_OK: /* No error. */ break; case SVZ_CODEC_MORE_IN: /* Needs more input data to continue. */ break; default: /* Unhandled. */ svz_log (LOG_ERROR, "%s: code: invalid return value: %d\n", codec->description, ret); break; } /* Call the saved @code{write_socket} callback with the new send buffer which is the output buffer of the codec. */ svz_codec_set_send_buffer (sock, data); if ((ret = data->write_socket (sock))) { svz_codec_unset_send_buffer (sock, data); return ret; } /* Save back changes made to the current send buffer. */ svz_codec_unset_send_buffer (sock, data); /* Restore old send buffer. */ svz_codec_restore_send_buffer (sock, data); return 0;}/* This callback is used as the @code{disconnected_socket} callback of the socket structure @var{sock}. It tries to release the resources of both the receiving and sending codec of @var{sock}. The routine is called by default if the codec socket structure @var{sock} gets disconnected for some external reason. */intsvz_codec_sock_disconnect (svz_socket_t *sock){ svz_codec_data_t *data; int (* disconnected) (svz_socket_t *); disconnected = NULL; /* Check and release receiving codec. */ if ((data = (svz_codec_data_t *) sock->recv_codec) != NULL) { disconnected = data->disconnected_socket; data->codec->finalize (data); svz_codec_sock_recv_revert (sock); } /* Check and release sending codec. */ if ((data = (svz_codec_data_t *) sock->send_codec) != NULL) { disconnected = data->disconnected_socket; data->codec->finalize (data); svz_codec_sock_send_revert (sock); } /* Run old @code{disconnected_socket} callback. */ if (disconnected != NULL) return disconnected (sock); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -