summaryrefslogtreecommitdiffstats
path: root/WebServer/Socket.cpp
diff options
context:
space:
mode:
authorfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-10-03 21:25:04 +0200
committerfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-10-03 21:25:04 +0200
commitaafef187ef856a36c3f8e599afea2dee44f08904 (patch)
treec84762cc768da2800a0f80b902c704e782bd29ef /WebServer/Socket.cpp
parentMCServer c++ source files (diff)
downloadcuberite-aafef187ef856a36c3f8e599afea2dee44f08904.tar
cuberite-aafef187ef856a36c3f8e599afea2dee44f08904.tar.gz
cuberite-aafef187ef856a36c3f8e599afea2dee44f08904.tar.bz2
cuberite-aafef187ef856a36c3f8e599afea2dee44f08904.tar.lz
cuberite-aafef187ef856a36c3f8e599afea2dee44f08904.tar.xz
cuberite-aafef187ef856a36c3f8e599afea2dee44f08904.tar.zst
cuberite-aafef187ef856a36c3f8e599afea2dee44f08904.zip
Diffstat (limited to 'WebServer/Socket.cpp')
-rw-r--r--WebServer/Socket.cpp278
1 files changed, 278 insertions, 0 deletions
diff --git a/WebServer/Socket.cpp b/WebServer/Socket.cpp
new file mode 100644
index 000000000..1ae3c9f37
--- /dev/null
+++ b/WebServer/Socket.cpp
@@ -0,0 +1,278 @@
+/*
+ Socket.cpp
+
+ Copyright (C) 2002-2004 René Nyffenegger
+
+ This source code is provided 'as-is', without any express or implied
+ warranty. In no event will the author be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this source code must not be misrepresented; you must not
+ claim that you wrote the original source code. If you use this source code
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original source code.
+
+ 3. This notice may not be removed or altered from any source distribution.
+
+ René Nyffenegger rene.nyffenegger@adp-gmbh.ch
+*/
+
+/*
+ Note on point 2:
+ THIS IS NOT THE ORIGINAL SOURCE1!!1!!!~!!~`1ONE!!`1
+*/
+
+#include "../source/cMCLogger.h"
+
+#include "Socket.h"
+#include <iostream>
+
+#ifndef _WIN32
+#include <cstring>
+#include <sys/time.h>
+#else
+#define MSG_NOSIGNAL (0)
+#endif
+
+#ifdef __MAC_NA
+#define MSG_NOSIGNAL (0)
+#endif
+
+using namespace std;
+
+int Socket::nofSockets_= 0;
+
+void Socket::Start() {
+#ifdef _WIN32
+ if (!nofSockets_) {
+ WSADATA info;
+ if (WSAStartup(MAKEWORD(2,0), &info)) {
+ throw "Could not start WSA";
+ }
+ }
+#endif
+ ++nofSockets_;
+}
+
+void Socket::End() {
+#ifdef _WIN32
+ WSACleanup();
+#endif
+}
+
+Socket::Socket() : s_(0) {
+ Start();
+ // UDP: use SOCK_DGRAM instead of SOCK_STREAM
+ s_ = socket(AF_INET,SOCK_STREAM,0);
+
+#ifdef _WIN32
+ if(s_ ==INVALID_SOCKET)
+#else
+ if(s_ < 0)
+#endif
+ {
+ throw "INVALID_SOCKET";
+ }
+
+ refCounter_ = new int(1);
+}
+
+Socket::Socket(SOCKET s) : s_(s) {
+ Start();
+ refCounter_ = new int(1);
+};
+
+Socket::~Socket() {
+ if (! --(*refCounter_)) {
+ Close();
+ delete refCounter_;
+ }
+
+ --nofSockets_;
+ if (!nofSockets_) End();
+}
+
+Socket::Socket(const Socket& o) {
+ refCounter_=o.refCounter_;
+ (*refCounter_)++;
+ s_ =o.s_;
+
+ nofSockets_++;
+}
+
+Socket& Socket::operator=(Socket& o) {
+ (*o.refCounter_)++;
+
+ refCounter_=o.refCounter_;
+ s_ =o.s_;
+
+ nofSockets_++;
+
+ return *this;
+}
+
+void Socket::Close() {
+ if( s_ )
+ {
+ closesocket(s_);
+ s_ = 0;
+ }
+}
+
+std::string Socket::ReceiveLine() {
+ std::string ret;
+ while (1) {
+ char r;
+
+ if (recv(s_, &r, 1, 0) <= 0 )
+ {
+ return "";
+ }
+
+ ret += r;
+ if (r == '\n') return ret;
+ }
+}
+
+void Socket::SendLine(std::string s) {
+ s += '\n';
+ if( send(s_,s.c_str(),s.length(),MSG_NOSIGNAL) <= 0 )
+ {
+ //printf("SendLine Socket error!! \n" );
+ Close();
+ }
+}
+
+void Socket::SendBytes(const std::string& s) {
+ if( send(s_,s.c_str(),s.length(), MSG_NOSIGNAL) <= 0 )
+ {
+ //printf("SendBytes Socket error!! \n" );
+ Close();
+ }
+}
+
+SocketServer::SocketServer(int port, int connections, TypeSocket type) {
+ sockaddr_in sa;
+
+ memset(&sa, 0, sizeof(sa));
+
+ sa.sin_family = PF_INET;
+ sa.sin_port = htons(port);
+ s_ = socket(AF_INET, SOCK_STREAM, 0);
+
+#ifdef _WIN32
+ if(s_ ==INVALID_SOCKET)
+#else
+ if(s_ < 0)
+#endif
+ {
+ LOG("WebServer: INVALID_SOCKET");
+ }
+
+ if(type==NonBlockingSocket) {
+ return;
+ }
+
+#ifdef _WIN32
+ char yes = 1;
+#else
+ int yes = 1;
+#endif
+ if (setsockopt(s_,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
+ LOG("WebServer: setsockopt == -1");
+ return;
+ }
+
+ /* bind the socket to the internet address */
+ if (bind(s_, (sockaddr *)&sa, sizeof(sockaddr_in)) == SOCKET_ERROR) {
+ closesocket(s_);
+ LOG("WebServer: INVALID_SOCKET");
+ }
+
+ listen(s_, connections);
+}
+
+Socket* SocketServer::Accept()
+{
+
+ SOCKET new_sock = accept(s_, 0, 0);
+#ifdef _WIN32
+ if(new_sock==INVALID_SOCKET || s_ == 0)
+#else
+ if(new_sock < 0 || s_ == 0)
+#endif
+ {
+ #ifdef _WIN32
+ int rc = WSAGetLastError();
+ if(rc==WSAEWOULDBLOCK) {
+ return 0; // non-blocking call, no request pending
+ }
+ else
+ #endif
+ {
+ //throw "Invalid Socket";
+ return 0;
+ }
+ }
+
+ Socket* r = new Socket(new_sock);
+ return r;
+}
+
+SocketClient::SocketClient(const std::string& host, int port) : Socket() {
+ std::string error;
+
+ hostent *he;
+ if ((he = gethostbyname(host.c_str())) == 0) {
+#ifdef _WIN32
+ error = strerror(errno);
+#endif
+ throw error;
+ }
+
+ sockaddr_in addr;
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr = *((in_addr *)he->h_addr);
+ memset(&(addr.sin_zero), 0, 8);
+
+ if (::connect(s_, (sockaddr *) &addr, sizeof(sockaddr))) {
+#ifdef _WIN32
+ error = strerror(WSAGetLastError());
+#endif
+ throw error;
+ }
+}
+
+#ifndef _WIN32
+struct timeval;
+#endif
+
+SocketSelect::SocketSelect(Socket const * const s1, Socket const * const s2, TypeSocket type) {
+ FD_ZERO(&fds_);
+ FD_SET(const_cast<Socket*>(s1)->s_,&fds_);
+ if(s2) {
+ FD_SET(const_cast<Socket*>(s2)->s_,&fds_);
+ }
+
+#ifdef _WIN32
+ TIMEVAL *ptval = 0;
+#else
+ timeval *ptval = 0;
+#endif
+
+ if (select (0, &fds_, (fd_set*) 0, (fd_set*) 0, ptval) == SOCKET_ERROR)
+ throw "Error in select";
+}
+
+bool SocketSelect::Readable(Socket const* const s) {
+ if (FD_ISSET(s->s_,&fds_)) return true;
+ return false;
+}