/* vim: ts=4 sw=4 sts=4 ff=unix fenc=utf-8 : * ===================================================================== * sc_stream_stream.c * Copyright (c) 2003 - 2011 sys0tem * LICENSE : * LGPL (GNU Lesser General Public License - Version 3,29 June 2007) * http://www.gnu.org/copyleft/lesser.html * or * EPL (Eclipse Public License - v1.0) * http://www.eclipse.org/legal/epl-v10.html * ===================================================================== */ #include <string.h> #include <sc_os.h> #include <sc_error.h> #include <sc_mmgr.h> #include <sc_stream_socket.h> typedef struct { socket_t sockfd; } SC_Stream_SocketInfo; /* --------------------------------------------------------------------- * プロトタイプ宣言 * --------------------------------------------------------------------- */ static int SC_Stream_socketRead(SC_Stream* strm, void* buff, size_t size); static int SC_Stream_socketWrite(SC_Stream* strm, const void* buff, size_t size); static bool SC_Stream_socketClose(SC_Stream* strm); /** * ソケットストリームを構築します。 * 構築に失敗した場合、NULL を返します。 * * @param fp ファイルディスクリプタ * @param buffSize 読み取りバッファサイズ * @return ストリーム */ SC_Stream* SC_Stream_newSocketStream(socket_t sockfd, size_t buffSize) { SC_Stream* strm; SC_Stream_SocketInfo* info; size_t size; size = sizeof(SC_Stream) + buffSize + sizeof(SC_Stream_SocketInfo); strm = (SC_Stream*) malloc(size); if (strm == NULL) { /* メモリ確保失敗 */ return NULL; } strm->_data.buff = (char*) (strm + 1); strm->_data.buffSize = buffSize; strm->_data.off = 0; strm->_data.size = 0; info = (SC_Stream_SocketInfo*) (strm->_data.buff + strm->_data.buffSize); info->sockfd = sockfd; strm->_strmInfo = info; strm->readc = SC_Stream_readc_; strm->read = SC_Stream_read_; strm->readExact = SC_Stream_readExact_; strm->readLine = SC_Stream_readLine_; strm->limitedRead = SC_Stream_limitedRead_; strm->writec = SC_Stream_writec_; strm->write = SC_Stream_write_; strm->writeExact = SC_Stream_writeExact_; strm->_readCore = SC_Stream_socketRead; strm->_writeCore = SC_Stream_socketWrite; strm->close = SC_Stream_socketClose; return strm; } /** * ソケットからデータを読み込みます。 * 終了した場合 0 を返します。 * エラーが発生した場合 -1 を返します。 * * @param strm ストリーム * @param buff バッファ * @param size サイズ * @return 読み取ったバッファサイズ */ static int SC_Stream_socketRead(SC_Stream* strm, void* buff, size_t size) { ssize_t readSize; int sockerr; SC_Stream_SocketInfo* info = (SC_Stream_SocketInfo*) strm->_strmInfo; do { /* SC_EINTR の場合、再度読み取る */ SC_setError(0); sockerr = 0; readSize = recv(info->sockfd, buff, size, 0); if (readSize < 0) { sockerr = SC_getSocketError(); } } while(sockerr == SC_EINTR); return readSize; } /** * ソケットにデータを書き込みます。 * * @param strm ストリーム * @param buff バッファ * @param size サイズ * @return 書き出したバッファサイズ */ static int SC_Stream_socketWrite(SC_Stream* strm, const void* buff, size_t size) { ssize_t writeSize; int sockerr; SC_Stream_SocketInfo* info = (SC_Stream_SocketInfo*) strm->_strmInfo; do { /* SC_EINTR の場合、再度読み取る */ SC_setError(0); sockerr = 0; writeSize = send(info->sockfd, buff, size, 0); if (writeSize < 0) { sockerr = SC_getSocketError(); } } while(sockerr == SC_EINTR); return writeSize; } /** * ストリームを close します。 * close に失敗した場合、false を返します。 * * @param strm ストリーム */ static bool SC_Stream_socketClose(SC_Stream* strm) { SC_Stream_SocketInfo* info; bool ret; if (strm->_strmInfo == NULL) { return false; } info = (SC_Stream_SocketInfo*) strm->_strmInfo; ret = SC_Socket_close(info->sockfd); return ret; }