diff options
Diffstat (limited to 'libs/networking')
57 files changed, 5459 insertions, 0 deletions
diff --git a/libs/networking/.dep.inc b/libs/networking/.dep.inc new file mode 100644 index 0000000..4560e55 --- /dev/null +++ b/libs/networking/.dep.inc @@ -0,0 +1,5 @@ +# This code depends on make tool being used +DEPFILES=$(wildcard $(addsuffix .d, ${OBJECTFILES})) +ifneq (${DEPFILES},) +include ${DEPFILES} +endif diff --git a/libs/networking/Makefile b/libs/networking/Makefile new file mode 100644 index 0000000..ec9de69 --- /dev/null +++ b/libs/networking/Makefile @@ -0,0 +1,128 @@ +# +# There exist several targets which are by default empty and which can be +# used for execution of your targets. These targets are usually executed +# before and after some main targets. They are: +# +# .build-pre: called before 'build' target +# .build-post: called after 'build' target +# .clean-pre: called before 'clean' target +# .clean-post: called after 'clean' target +# .clobber-pre: called before 'clobber' target +# .clobber-post: called after 'clobber' target +# .all-pre: called before 'all' target +# .all-post: called after 'all' target +# .help-pre: called before 'help' target +# .help-post: called after 'help' target +# +# Targets beginning with '.' are not intended to be called on their own. +# +# Main targets can be executed directly, and they are: +# +# build build a specific configuration +# clean remove built files from a configuration +# clobber remove all built files +# all build all configurations +# help print help mesage +# +# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and +# .help-impl are implemented in nbproject/makefile-impl.mk. +# +# Available make variables: +# +# CND_BASEDIR base directory for relative paths +# CND_DISTDIR default top distribution directory (build artifacts) +# CND_BUILDDIR default top build directory (object files, ...) +# CONF name of current configuration +# CND_PLATFORM_${CONF} platform name (current configuration) +# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration) +# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration) +# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration) +# CND_PACKAGE_DIR_${CONF} directory of package (current configuration) +# CND_PACKAGE_NAME_${CONF} name of package (current configuration) +# CND_PACKAGE_PATH_${CONF} path to package (current configuration) +# +# NOCDDL + + +# Environment +MKDIR=mkdir +CP=cp +CCADMIN=CCadmin + + +# build +build: .build-post + +.build-pre: +# Add your pre 'build' code here... + +.build-post: .build-impl +# Add your post 'build' code here... + + +# clean +clean: .clean-post + +.clean-pre: +# Add your pre 'clean' code here... + +.clean-post: .clean-impl +# Add your post 'clean' code here... + + +# clobber +clobber: .clobber-post + +.clobber-pre: +# Add your pre 'clobber' code here... + +.clobber-post: .clobber-impl +# Add your post 'clobber' code here... + + +# all +all: .all-post + +.all-pre: +# Add your pre 'all' code here... + +.all-post: .all-impl +# Add your post 'all' code here... + + +# build tests +build-tests: .build-tests-post + +.build-tests-pre: +# Add your pre 'build-tests' code here... + +.build-tests-post: .build-tests-impl +# Add your post 'build-tests' code here... + + +# run tests +test: .test-post + +.test-pre: +# Add your pre 'test' code here... + +.test-post: .test-impl +# Add your post 'test' code here... + + +# help +help: .help-post + +.help-pre: +# Add your pre 'help' code here... + +.help-post: .help-impl +# Add your post 'help' code here... + + + +# include project implementation makefile +include nbproject/Makefile-impl.mk + +# include project make variables +include nbproject/Makefile-variables.mk diff --git a/libs/networking/include/AbstractSocket.h b/libs/networking/include/AbstractSocket.h new file mode 100644 index 0000000..ff76f52 --- /dev/null +++ b/libs/networking/include/AbstractSocket.h @@ -0,0 +1,63 @@ +/** + * ======================== legal notice ====================== + * + * File: AbstractSocket.h + * Created: 4. Juli 2012, 07:13 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef ABSTRACTSOCKET_H +#define ABSTRACTSOCKET_H + +#include <ConnectionPoint.h> +#include <sys/socket.h> + +class cAbstractSocket { +public: + virtual ~cAbstractSocket(); + const cConnectionPoint *ThisSide(void) const { return thisSide; } + const cConnectionPoint *OtherSide(void) const { return others[0]; } + cConnectionPoint *ThisSide(void) { return thisSide; } + cConnectionPoint *OtherSide(void) { return others[0]; } + virtual void ConfigureSocket(int Socket) {} + +protected: + cAbstractSocket(int Port, int Queue = 1); + cAbstractSocket(const char *ServerName, int Port); + bool Connect(); + bool Open(int Port); + cConnectionPoint *Accept(int Port, int TimeoutMs = -1); + bool ForceBlockingIO(void) const { return blocking; } + void SetBlockingIO(bool ForceBlockingIO = true); + cConnectionPoint *GetNameAndAddress(int Socket, struct sockaddr *sa, socklen_t sa_size); + void Close(void); + +private: + int sock; + int queue; + bool blocking; + cConnectionPoint *thisSide; + ConnectionPointList others; ///< client sockets have only one other side, + ///< but server sockets can have multiple connections open at the same time, + ///< so we probabely need a container here. + // cConnectionPointInfo *FetchLocalInfo(int Socket, struct addrinfo *AI); + }; + +#endif /* ABSTRACTSOCKET_H */ + diff --git a/libs/networking/include/Authorization.h b/libs/networking/include/Authorization.h new file mode 100644 index 0000000..fa04bd4 --- /dev/null +++ b/libs/networking/include/Authorization.h @@ -0,0 +1,115 @@ +/** + * ======================== legal notice ====================== + * + * File: Authorization.h + * Created: 3. Juli 2012, 17:27 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef AUTHORIZATION_H +#define AUTHORIZATION_H + +#include <HTTPRequest.h> +#include <Principal.h> +#include <string.h> +#include <stdlib.h> +#include <stddef.h> +#include <time.h> +#include <ManagedVector.h> + +class cAuthorization { +public: + cAuthorization(const cHTTPRequest &OriginalRequest, char *NOnceFromHeap); + cAuthorization(cHTTPRequest::HTTPRequestMethod Method, const char *Raw); + cAuthorization(const cAuthorization &other); + cAuthorization(const cPrincipal *Principal, cHTTPRequest::HTTPRequestMethod Method, const cAuthorization &other); + virtual ~cAuthorization(); + cAuthorization &operator =(const cAuthorization &other); + size_t Write(char *Buffer, size_t BufSize); + const char *CalculateResponse(const char *Uri = NULL, const char *Username = NULL, const char *Password = NULL); + void Dump(void) const; + const char *Uri(void) const { return uri; } + const char *Response(void) const { return response; } + const char *CNOnce(void) const { return cnonce; } + const char *NOnce(void) const { return nonce; } + const char *Opaque(void) const { return opaque; } + const char *UserID(void) const { + if (principal) return principal->Name(); + else if (tmp) return tmp->Name(); + return NULL; + } + const char *UserCredential(void) const { + if (principal) return principal->Hash(); + else if (tmp) return tmp->Hash(); + return NULL; + } + const char *Realm(void) const { + if (principal) return principal->Realm(); + else if (tmp) return tmp->Realm(); + return NULL; + } + void SetUser(const char *UserID, const char *Password); + char *CalculateA1(const char *Username = NULL, const char *Password = NULL); + char *CalculateA2(const char *Uri); + +protected: + virtual void ParseRawBuffer(const char *Raw); + virtual void CreateClientHash(); + const cPrincipal *Principal(void) const { return principal; } + void SetAttribute(char *Name, const char *Value); + void SetOpaque(char *Value); + void SetPrincipal(const cPrincipal *Principal) { principal = Principal; } + +private: + void SetServerID(const char *ServerID) { free(serverID); serverID = ServerID ? strdup(ServerID) : NULL; } + void SetUri(const char *Uri) { free(uri); uri = Uri ? strdup(Uri) : NULL; } + cPrincipal *tmp; + const cPrincipal *principal; + cHTTPRequest::HTTPRequestMethod method; + char *serverID; + bool sessAlgo; + char *nonce; + char *uri; + char *response; + char *opaque; + char *cnonce; + char *qop; + int counter; + time_t authTime; + friend class cHTTPResponse; + friend class cHTTPRequest; + friend class cAuthorizations; + friend class cConnectionHandler; + }; + +class cConnectionPoint; +class cAuthorizations : public cManagedVector { +public: + cAuthorizations(); + virtual ~cAuthorizations(); + + cAuthorization *FindAuthorization(const char *SessionID); + void Del(cAuthorization *Auth2Invalidate); + const cAuthorization &CreateAuthorization(const cHTTPRequest &OriginalRequest, const cConnectionPoint &client, unsigned long connectionNumber); + static char *CreateNOnce(const cConnectionPoint &client, unsigned long connectionNumber); + static char *CreateSessionID(const cHTTPRequest &OriginalRequest, time_t AuthTime); + }; + +#endif /* AUTHORIZATION_H */ + diff --git a/libs/networking/include/ClientSocket.h b/libs/networking/include/ClientSocket.h new file mode 100644 index 0000000..0dc899e --- /dev/null +++ b/libs/networking/include/ClientSocket.h @@ -0,0 +1,39 @@ +/** + * ======================== legal notice ====================== + * + * File: ClientSocket.h + * Created: 4. Juli 2012, 07:25 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef CLIENTSOCKET_H +#define CLIENTSOCKET_H + +#include <AbstractSocket.h> + +class cClientSocket : public cAbstractSocket { +public: + cClientSocket(const char *serverName, int Port); + virtual ~cClientSocket(); + bool Connect(void); + void Close(void); + }; + +#endif /* CLIENTSOCKET_H */ + diff --git a/libs/networking/include/ConnectionHandler.h b/libs/networking/include/ConnectionHandler.h new file mode 100644 index 0000000..c4232be --- /dev/null +++ b/libs/networking/include/ConnectionHandler.h @@ -0,0 +1,77 @@ +/** + * ======================== legal notice ====================== + * + * File: ConnectionHandler.h + * Created: 4. Juli 2012, 07:32 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef CONNECTIONHANDLER_H +#define CONNECTIONHANDLER_H + +#include <Thread.h> +#include <ServerConfig.h> +#include <sys/types.h> + +class cConnectionPoint; +class cAuthorization; +class cHTTPResponse; +class cHTTPRequest; +class cFileHandler; +class cHTTPRequestHandler; +class cStringBuilder; +class cConnectionHandler : public cThread { +public: + cConnectionHandler(cConnectionPoint &Client, cServerConfig &Config, bool StayConnected = false); + virtual ~cConnectionHandler(); + + void Action(void); + + bool AuthorizationRequired(void) { return config.AuthorizationRequired(); } + const char *NOnce(void) const { return nonce; } + bool StayConnected(void) const { return stayConnected; } + virtual void Cancel(int WaitSeconds = 0); + + static void RegisterRequestHandler(const char *UrlPrefix, cHTTPRequestHandler *CommandHandler); + static void RegisterDefaultHandler(cHTTPRequestHandler *DefaultHandler); + static void Cleanup(void); + +protected: + cAuthorizations &Authorizations(void) { return config.authorizations; } + cServerSocket &ServerSocket(void) { return config.server; } + cHTTPResponse *ProcessRequest(cHTTPRequest &Request); + void TransferResponse(cHTTPResponse *Response); + void SetNonce(char *NOnce) { nonce = NOnce; } + bool IsAuthorizationValid(cAuthorization *ServerAuth, const cHTTPRequest &request); + void Usage(cStringBuilder &sb); + +private: + void Init(void); + cServerConfig &config; + cConnectionPoint &client; + unsigned long connectionNumber; + size_t bufSize; + char *scratch; + char *nonce; + bool stayConnected; + friend class cTestUnit; + }; + +#endif /* CONNECTIONHANDLER_H */ + diff --git a/libs/networking/include/ConnectionPoint.h b/libs/networking/include/ConnectionPoint.h new file mode 100644 index 0000000..8980adb --- /dev/null +++ b/libs/networking/include/ConnectionPoint.h @@ -0,0 +1,60 @@ +/** + * ======================== legal notice ====================== + * + * File: ConnectionPoint.h + * Created: 4. Juli 2012, 06:29 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef CONNECTIONPOINT_H +#define CONNECTIONPOINT_H + +#include <stddef.h> +#include <vector> + +class cConnectionPoint { +public: + cConnectionPoint(const char *NameOrIP, int Port, const char *RealName = NULL); + virtual ~cConnectionPoint(); + + int IOWait(long MilliSeconds = 300); + const char *HostName(void) const { return nameOrIP; } + const char *RealName(void) const { return realName ? realName : "unknown"; } + const char *ToString() const { return combined ? combined : AssembleCombined(); } + int Port(void) const { return port; } + int Socket(void) const { return sock; } + +private: + char *nameOrIP; + char *realName; + mutable char *combined; + int port; + int sock; + const char *AssembleCombined(void) const; + void Close(void); + void SetSocket(int Socket) { sock = Socket; } + void SetRealName(const char *Name); + friend class cAbstractSocket; + friend class cConnectionHandler; + }; + +typedef std::vector<cConnectionPoint *> ConnectionPointList; + +#endif /* CONNECTIONPOINT_H */ + diff --git a/libs/networking/include/Credentials.h b/libs/networking/include/Credentials.h new file mode 100644 index 0000000..c27532d --- /dev/null +++ b/libs/networking/include/Credentials.h @@ -0,0 +1,61 @@ +/** + * ======================== legal notice ====================== + * + * File: Credentials.h + * Created: 3. Juli 2012, 14:37 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef CREDENTIALS_H +#define CREDENTIALS_H + +#include <Principal.h> +#include <string> +#include <tr1/unordered_map> + +class cCredentials { +public: + typedef std::tr1::unordered_map<std::string, cPrincipal *>::const_iterator const_iterator; + cCredentials(); + virtual ~cCredentials(); + + const cPrincipal *FindPrincipal(const char *Name, const char *Realm); + const char *ApplicationRealm(void) const; + void SetApplicationRealm(const char *ApplicationRealm = "knownUser@myApp"); + + int Load(const char *FileName); + int Store(const char *FileName); + + void Put(const char *Key, cPrincipal *p); + cPrincipal *Get(const char *Key); + void Clear(void); + + const_iterator begin() { return internalMap.begin(); } + const_iterator end() { return internalMap.end(); } + +private: + cPrincipal *parsePrincipal(char *buf, size_t bufSize); + std::tr1::unordered_map<std::string, cPrincipal *> internalMap; + typedef std::tr1::unordered_map<std::string, cPrincipal *>::iterator iterator; + }; + +extern cCredentials Credentials; + +#endif /* CREDENTIALS_H */ + diff --git a/libs/networking/include/HTTPAuthorizationRequest.h b/libs/networking/include/HTTPAuthorizationRequest.h new file mode 100644 index 0000000..d3d566d --- /dev/null +++ b/libs/networking/include/HTTPAuthorizationRequest.h @@ -0,0 +1,41 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPAuthorizationRequest.h + * Created: 4. Juli 2012, 07:41 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPAUTHORIZATIONREQUEST_H +#define HTTPAUTHORIZATIONREQUEST_H + +#include <HTTPResponse.h> + +class cHTTPRequest; +class cHTTPAuthorizationRequest : public cHTTPResponse { +///< the server requires authorization, so the message is a response +///< The clients response is another (repeated) request with authentication headers +public: + cHTTPAuthorizationRequest(const cHTTPRequest &OriginalRequest, char *NOnceFromHeap); + cHTTPAuthorizationRequest(const cAuthorization &Authorization); + virtual ~cHTTPAuthorizationRequest(); + }; + +#endif /* HTTPAUTHORIZATIONREQUEST_H */ + diff --git a/libs/networking/include/HTTPFileResponse.h b/libs/networking/include/HTTPFileResponse.h new file mode 100644 index 0000000..0457850 --- /dev/null +++ b/libs/networking/include/HTTPFileResponse.h @@ -0,0 +1,48 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPFileResponse.h + * Created: 4. Juli 2012, 07:50 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPFILERESPONSE_H +#define HTTPFILERESPONSE_H + +#include <HTTPResponse.h> + +class cHTTPFileResponse : public cHTTPResponse { +public: + cHTTPFileResponse(const char *RealPath); + virtual ~cHTTPFileResponse(); + const char *RealPath(void) const { return realPath; } + + virtual size_t ReadContentChunk(char *Buf, size_t bufSize); + +protected: + cHTTPFileResponse(); + +private: + void DetermineTypeAndSize(const char *Path); + const char *realPath; + int fd; + }; + +#endif /* HTTPFILERESPONSE_H */ + diff --git a/libs/networking/include/HTTPMessage.h b/libs/networking/include/HTTPMessage.h new file mode 100644 index 0000000..cb88c69 --- /dev/null +++ b/libs/networking/include/HTTPMessage.h @@ -0,0 +1,92 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPMessage.h + * Created: 3. Juli 2012, 17:40 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPMESSAGE_H +#define HTTPMESSAGE_H + +#define MT_Html "text/html" + +#include <ManagedMap.h> + +class cAuthorization; +class cHTTPMessage { +public: + typedef enum { Unknown, HTTP_1_0, HTTP_1_1 } HTTPProtocol; + + cHTTPMessage(HTTPProtocol Proto=HTTP_1_1); + virtual ~cHTTPMessage(); + + HTTPProtocol Protocol(void) { return protocol; } + const char *ProtocolString(void); + const char *ContentType(void) const { return contentType; } + virtual size_t ContentSize(void) const; + const char *GetHeader(const char *Name) const; + const cAuthorization *Authorization(void) const { return auth; } + void SetAuthorization(cAuthorization *Authorization); + size_t WritePrefix(char *Buffer, size_t BufSize); ///< writes message header, so content will follow + virtual void Dump(void); + +protected: + enum ParseState { + ExpectFormat + , ExpectURL + , ExpectProtocol + , ExpectStatus + , ExpectHeader + , ExpectContent + }; + enum ParseResult { + UnknownError + , UnsupportedFormat + , InvalidURL + , InvalidName + , UnsupportedProtocol + , Continue + , Done + }; + virtual size_t WriteFirstLine(char *Buffer, size_t BufSize) = 0; + virtual void SetContentType(const char *ContentType); + virtual void SetContentSize(size_t ContentSize) { contentSize = ContentSize; } + void SetHeader(const char *Name, const char *Value); + void SetProtocol(HTTPProtocol Protocol) { protocol = Protocol; } + cAuthorization *Authorization(void) { return auth; } + char *FormatTime(time_t time); + const cManagedMap &Headers() const { return header; } + int WriteTime(char *Buffer, size_t BufSize); + void Reset(void); + +private: + HTTPProtocol protocol; + time_t timeStamp; + cManagedMap header; + cAuthorization *auth; + size_t contentSize; + char *contentType; + friend class cMediaListHandler; + friend class cConnectionHandler; + friend class cTestUnit; + }; + +#endif /* HTTPMESSAGE_H */ + diff --git a/libs/networking/include/HTTPParser.h b/libs/networking/include/HTTPParser.h new file mode 100644 index 0000000..9ed8169 --- /dev/null +++ b/libs/networking/include/HTTPParser.h @@ -0,0 +1,47 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPParser.h + * Created: 10. Juli 2012, 08:37 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPPARSER_H +#define HTTPPARSER_H + +class cHTTPMessage; +class cHTTPRequest; +class cHTTPResponse; +class cHTTPParser +{ +public: + cHTTPParser(); + virtual ~cHTTPParser(); + + cHTTPMessage *ParseMessage(const char *MessageBuf); + +protected: + cHTTPRequest *parseRequest(const char *MessageBuf); + cHTTPResponse *parseResponse(const char *MessageBuf); + +private: +}; + +#endif /* HTTPPARSER_H */ + diff --git a/libs/networking/include/HTTPRequest.h b/libs/networking/include/HTTPRequest.h new file mode 100644 index 0000000..87c78d7 --- /dev/null +++ b/libs/networking/include/HTTPRequest.h @@ -0,0 +1,62 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPRequest.h + * Created: 3. Juli 2012, 17:54 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPREQUEST_H +#define HTTPREQUEST_H + +#include <HTTPMessage.h> +#include <Url.h> + +class cHTTPResponse; +class cHTTPRequest : public cHTTPMessage { +///< a message sent from client to server to access a certain resource +public: + typedef enum { INVALID, GET, POST } HTTPRequestMethod; + cHTTPRequest(const char *MessageBuf); + cHTTPRequest(HTTPRequestMethod Format, const char *Url); + cHTTPRequest(const cHTTPResponse &res, const char *Url); + virtual ~cHTTPRequest(); + HTTPRequestMethod Method(void) const { return method; } + const cUrl &Url() const { return url; } + cUrl &Url() { return url; } + const char *UserAgent() const; + const char *ClientHost(void) const; + void SetUser(const char *UserID, const char *Password); + +protected: + void SetMethod(HTTPRequestMethod Method) { method = Method; } + void SetURL(const char *Url); + virtual size_t WriteFirstLine(char *Buffer, size_t BufSize); + void ParseMessage(const char *MessageBuf); + +private: + HTTPRequestMethod method; + cUrl url; + friend class HTTPParser; + }; + +extern const char *requestMethod2String(cHTTPRequest::HTTPRequestMethod Method); + +#endif /* HTTPREQUEST_H */ + diff --git a/libs/networking/include/HTTPRequestHandler.h b/libs/networking/include/HTTPRequestHandler.h new file mode 100644 index 0000000..99c31d2 --- /dev/null +++ b/libs/networking/include/HTTPRequestHandler.h @@ -0,0 +1,48 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPRequestHandler.h + * Created: 4. Juli 2012, 15:12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPREQUESTHANDLER_H +#define HTTPREQUESTHANDLER_H + +class cHTTPRequest; +class cHTTPResponse; +class cStringBuilder; +class cHTTPRequestHandler { +public: + cHTTPRequestHandler(); + virtual ~cHTTPRequestHandler(); + + virtual cHTTPResponse *ProcessRequest(cHTTPRequest &Request) = 0; + virtual void Usage(cStringBuilder &sb) = 0; + + const char *ID() const { return prefix; } + +private: + void SetID(const char *UrlPrefix); + char *prefix; + friend class cHTTPRequestHandlers; + }; + +#endif /* HTTPREQUESTHANDLER_H */ + diff --git a/libs/networking/include/HTTPResponse.h b/libs/networking/include/HTTPResponse.h new file mode 100644 index 0000000..afa4ae5 --- /dev/null +++ b/libs/networking/include/HTTPResponse.h @@ -0,0 +1,73 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPResponse.h + * Created: 4. Juli 2012, 06:03 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPRESPONSE_H +#define HTTPRESPONSE_H + +#define MT_Unknown "unsupported/unknown" +#define MT_CSS "text/css" +#define MT_JavaScript "application/javascript" +#define MT_Gif "image/gif" +#define MT_Png "image/png" +#define MT_Ico "image/x-icon" +#define MT_Jpg "image/jpeg" +#define MT_Xml "application/xml" +#define MT_XmlDtd "application/xml-dtd" + +#include <HTTPStatus.h> +#include <HTTPMessage.h> +#include <StringBuilder.h> + +class cHTTPResponse : public cHTTPMessage { +public: + cHTTPResponse(HTTPStatusCode Status = HTTP_OK); + ///< server side creates a response by status code + cHTTPResponse(const char *Buffer); + ///< client side creates a response from receiving buffer + virtual ~cHTTPResponse(); + + HTTPStatusCode Status(void) const { return status; } + virtual size_t ContentSize(void) const; + virtual void SetContentType(const char *ContentType) { cHTTPMessage::SetContentType(ContentType); } + virtual void SetContentSize(size_t ContentSize) { cHTTPMessage::SetContentSize(ContentSize); } + cStringBuilder &StringBuilder(void) { return content; } + + static const char *ServerID(void); + static void SetServerID(const char *ServerID); + +protected: + virtual size_t WriteFirstLine(char *Buffer, size_t BufSize); + void ParseMessage(const char *MessageBuf); + +private: + virtual size_t ReadContentChunk(char *Buf, size_t bufSize); + void SetDefaultStatusBody(HTTPStatusCode Status); + HTTPStatusCode status; + cStringBuilder content; + friend class cConnectionHandler; + friend class HTTPParser; + }; + +#endif /* HTTPRESPONSE_H */ + diff --git a/libs/networking/include/HTTPServer.h b/libs/networking/include/HTTPServer.h new file mode 100644 index 0000000..4dbe5a8 --- /dev/null +++ b/libs/networking/include/HTTPServer.h @@ -0,0 +1,61 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPServer.h + * Created: 4. Juli 2012, 12:16 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPSERVER_H +#define HTTPSERVER_H + +#include <ServerConfig.h> +#include <Mutex.h> +#include <vector> + +class cThread; +class cHTTPServer /* : public cThread */ { +public: + cHTTPServer(cServerConfig &Config); + ~cHTTPServer(); + + bool Start(void); + void Stop(void); + +protected: + void Action(void); + bool AuthorizationRequired(void) const { return config.AuthorizationRequired(); } + bool Running(void); + cServerSocket &ServerSocket() { return config.server; } + +private: +#ifdef LIVE_CLEANUP + void Cleanup(cThread *ThreadContext); + static int cleanerThread(void *opaque, cThread *ThreadContext); + cThread *cleaner; + cMutex poolMutex; +#else + void Cleanup(); +#endif + cServerConfig &config; + std::vector<cThread *> *threads; + }; + +#endif /* HTTPSERVER_H */ + diff --git a/libs/networking/include/HTTPStatus.h b/libs/networking/include/HTTPStatus.h new file mode 100644 index 0000000..10ff080 --- /dev/null +++ b/libs/networking/include/HTTPStatus.h @@ -0,0 +1,74 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPStatus.h + * Created: 3. Juli 2012, 17:34 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef HTTPSTATUS_H +#define HTTPSTATUS_H + +typedef enum { + HTTP_Continue = 100 +, HTTP_SwitchProtocol = 101 +, HTTP_OK = 200 +, HTTP_Created = 201 +, HTTP_Accepted = 202 +, HTTP_NoContent = 204 +, HTTP_ResetContent = 205 +, HTTP_PartialContent = 206 +, HTTP_MultipleChoices = 300 +, HTTP_MovedPermanently = 301 +, HTTP_Found = 302 +, HTTP_SeeOther = 303 +, HTTP_NotModified = 304 +, HTTP_UseProxy = 305 +, HTTP_MovedTemporarily = 307 +, HTTP_BadRequest = 400 +, HTTP_UnAuthorized = 401 +, HTTP_PaymentRequired = 402 +, HTTP_Forbidden = 403 +, HTTP_NotFound = 404 +, HTTP_MethodNotAllowed = 405 +, HTTP_NotAcceptable = 406 +, HTTP_ProxyAuthenticationRequired = 407 +, HTTP_RequestTimeout = 408 +, HTTP_Conflict = 409 +, HTTP_Gone = 410 +, HTTP_LengthRequired = 411 +, HTTP_PreconditionFailed = 412 +, HTTP_RequestTooLarge = 413 +, HTTP_RequestURIToLong = 414 +, HTTP_UnsupportedMediaType = 415 +, HTTP_RequestRangeNotSatisfiable = 416 +, HTTP_ExpectationFailed = 417 +, HTTP_InternalServerError = 500 +, HTTP_NotImplemented = 501 +, HTTP_BadGateway = 502 +, HTTP_ServiceUnavailable = 503 +, HTTP_GatewayTimeout = 504 +, HTTP_VersionNotSupported = 505 + } HTTPStatusCode; + +extern const char *httpStatus2Text(int Status); +extern HTTPStatusCode strtoHTTPStatus(const char *p); + +#endif /* HTTPSTATUS_H */ + diff --git a/libs/networking/include/Principal.h b/libs/networking/include/Principal.h new file mode 100644 index 0000000..49afbde --- /dev/null +++ b/libs/networking/include/Principal.h @@ -0,0 +1,64 @@ +/** + * ======================== legal notice ====================== + * + * File: Principal.h + * Created: 3. Juli 2012, 12:50 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef PRINCIPAL_H +#define PRINCIPAL_H + +class cPrincipal { +public: + cPrincipal(const char *Name, const char *Realm); + cPrincipal(const cPrincipal &other); + virtual ~cPrincipal(); + cPrincipal &operator =(const cPrincipal &other); + const char *operator *(void) { return name; } + + void CreateHash(const char *Password); + + const char *Name(void) const { return name; } + const char *Realm(void) const { return realm; } + const char *ExtendedInfo(void) const { return xinfo; } + int Age(void) const { return age; } + void SetAge(int Age) { age = Age; } + const char *Hash(void) const { return hash; } + + void Dump(void) const; + +protected: + void SetName(const char *Name); + void SetRealm(const char *Realm); + void SetExtendedInfo(const char *Info); + void SetHash(const char *Hash); + +private: + char *name; + char *realm; + char *hash; + char *xinfo; + int age; + friend class cAuthorization; + friend class cCredentials; + }; + +#endif /* PRINCIPAL_H */ + diff --git a/libs/networking/include/ServerConfig.h b/libs/networking/include/ServerConfig.h new file mode 100644 index 0000000..f64b5f5 --- /dev/null +++ b/libs/networking/include/ServerConfig.h @@ -0,0 +1,56 @@ +/** + * ======================== legal notice ====================== + * + * File: ServerConfig.h + * Created: 8. Juli 2012, 06:12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef SERVERCONFIG_H +#define SERVERCONFIG_H + +#include <ServerSocket.h> +#include <Authorization.h> + +class cServerConfig +{ +public: + cServerConfig(int Port); + virtual ~cServerConfig(); + + bool AuthorizationRequired(void) { return authorizationRequired; } + const char *AppIconPath(void) const { return appIconPath; } + const char *DocumentRoot(void) const { return documentRoot; } + + void SetAppIcon(const char *AppIcon); + void SetAuthorizationRequired(bool Authorize) { authorizationRequired = Authorize; } + void SetDocumentRoot(const char *DocumentRoot); + +private: + cServerSocket server; + cAuthorizations authorizations; + bool authorizationRequired; + char *documentRoot; + char *appIconPath; + friend class cHTTPServer; + friend class cConnectionHandler; +}; + +#endif /* SERVERCONFIG_H */ + diff --git a/libs/networking/include/ServerSocket.h b/libs/networking/include/ServerSocket.h new file mode 100644 index 0000000..2fc17fb --- /dev/null +++ b/libs/networking/include/ServerSocket.h @@ -0,0 +1,52 @@ +/** + * ======================== legal notice ====================== + * + * File: ServerSocket.h + * Created: 4. Juli 2012, 07:28 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef SERVERSOCKET_H +#define SERVERSOCKET_H + +#include <AbstractSocket.h> + +class cServerSocket : public cAbstractSocket { +public: + cServerSocket(int Port, int Queue = 1); + virtual ~cServerSocket(); + bool Open(void); + bool Active(void) const { return active; } + void SetActive(bool Active = true) { active = Active; } + cConnectionPoint *Accept(void); + int Port(void) const { return port; } + int ReUseAddress(void) const; + void SetReUseAddress(int ReUse); + void ConfigureSocket(int Socket); + bool ForceBlockingIO(void) const; + void SetBlockingIO(bool ForceBlockingIO = true); + +private: + int port; ///< in case we plenty open and close server sockets + ///< we need a place to remember the server port + bool active; + }; + +#endif /* SERVERSOCKET_H */ + diff --git a/libs/networking/include/Url.h b/libs/networking/include/Url.h new file mode 100644 index 0000000..c88a00a --- /dev/null +++ b/libs/networking/include/Url.h @@ -0,0 +1,67 @@ +/** + * ======================== legal notice ====================== + * + * File: Url.h + * Created: 4. Juli 2012, 05:42 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#ifndef URL_H +#define URL_H + +#include <stddef.h> +#include <string> +#include <tr1/unordered_map> +class cURLEncoder; +class cURLDecoder; + +class cUrl { +///< splits an url into machine readable parts: +///< from top-level sight, an url consists of url and querystring. Looking bit closer, +///< the url consists of toplevel and path, where as the querystring is a list of +///< name/value tuples with value being an optional part. +public: + cUrl(const char *RawURL); + virtual ~cUrl(); + const char *Parameter(const char *Name); + void SetParameter(const char* Name, const char* Value = NULL); + size_t EstimatedSize(void) const; ///< is a rough guess about the size of the final encoded url + void ParseURL(const char *URL); + char *ToString(void) const; ///< writes the url to a newly allocated buffer + int WriteBuf(char *buf, size_t bufSize) const; ///< writes the url to preexisting buffer + ///< returns the characters written. -1 as return value indicates a buffer overrun. + const char * Path() const { return path; } +#ifdef DEBUG + void Dump(void); +#endif + static void Cleanup(void); + +protected: + void ParseQueryString(const char *QueryString); + cURLEncoder *Encoder(void) const; + cURLDecoder *Decoder(void) const; + +private: + typedef std::tr1::unordered_map<std::string, std::string> ParameterMap; + char *path; + ParameterMap parameters; + }; + +#endif /* URL_H */ + diff --git a/libs/networking/nbproject/Makefile-Debug.mk b/libs/networking/nbproject/Makefile-Debug.mk new file mode 100644 index 0000000..1187090 --- /dev/null +++ b/libs/networking/nbproject/Makefile-Debug.mk @@ -0,0 +1,193 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Environment +MKDIR=mkdir +CP=cp +GREP=grep +NM=nm +CCADMIN=CCadmin +RANLIB=ranlib +CC=gcc +CCC=g++ +CXX=g++ +FC=gfortran +AS=as + +# Macros +CND_PLATFORM=GNU-Linux-x86 +CND_CONF=Debug +CND_DISTDIR=dist +CND_BUILDDIR=build + +# Include project Makefile +include Makefile + +# Object Directory +OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM} + +# Object Files +OBJECTFILES= \ + ${OBJECTDIR}/src/HTTPRequest.o \ + ${OBJECTDIR}/src/ServerSocket.o \ + ${OBJECTDIR}/src/HTTPAuthorizationRequest.o \ + ${OBJECTDIR}/src/Url.o \ + ${OBJECTDIR}/src/Principal.o \ + ${OBJECTDIR}/src/Authorization.o \ + ${OBJECTDIR}/src/ServerConfig.o \ + ${OBJECTDIR}/src/HTTPServer.o \ + ${OBJECTDIR}/src/ConnectionPoint.o \ + ${OBJECTDIR}/src/HTTPResponse.o \ + ${OBJECTDIR}/src/ConnectionHandler.o \ + ${OBJECTDIR}/src/Credentials.o \ + ${OBJECTDIR}/src/HTTPRequestHandler.o \ + ${OBJECTDIR}/src/HTTPMessage.o \ + ${OBJECTDIR}/src/HTTPFileResponse.o \ + ${OBJECTDIR}/src/HTTPParser.o \ + ${OBJECTDIR}/src/ClientSocket.o \ + ${OBJECTDIR}/src/AbstractSocket.o \ + ${OBJECTDIR}/src/HTTPStatus.o + + +# C Compiler Flags +CFLAGS= + +# CC Compiler Flags +CCFLAGS=-std=gnu++0x -fomit-frame-pointer -fPIC -pthread -Wall -Wno-parentheses -Wno-switch -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wtype-limits -Wundef -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -ansi +CXXFLAGS=-std=gnu++0x -fomit-frame-pointer -fPIC -pthread -Wall -Wno-parentheses -Wno-switch -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wtype-limits -Wundef -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -ansi + +# Fortran Compiler Flags +FFLAGS= + +# Assembler Flags +ASFLAGS= + +# Link Libraries and Options +LDLIBSOPTIONS= + +# Build Targets +.build-conf: ${BUILD_SUBPROJECTS} + "${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + +${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a: ${OBJECTFILES} + ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} + ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + ${AR} -rv ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a ${OBJECTFILES} + $(RANLIB) ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + +${OBJECTDIR}/src/HTTPRequest.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPRequest.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPRequest.o src/HTTPRequest.cc + +${OBJECTDIR}/src/ServerSocket.o: nbproject/Makefile-${CND_CONF}.mk src/ServerSocket.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ServerSocket.o src/ServerSocket.cc + +${OBJECTDIR}/src/HTTPAuthorizationRequest.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPAuthorizationRequest.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPAuthorizationRequest.o src/HTTPAuthorizationRequest.cc + +${OBJECTDIR}/src/Url.o: nbproject/Makefile-${CND_CONF}.mk src/Url.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Url.o src/Url.cc + +${OBJECTDIR}/src/Principal.o: nbproject/Makefile-${CND_CONF}.mk src/Principal.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Principal.o src/Principal.cc + +${OBJECTDIR}/src/Authorization.o: nbproject/Makefile-${CND_CONF}.mk src/Authorization.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Authorization.o src/Authorization.cc + +${OBJECTDIR}/src/ServerConfig.o: nbproject/Makefile-${CND_CONF}.mk src/ServerConfig.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ServerConfig.o src/ServerConfig.cc + +${OBJECTDIR}/src/HTTPServer.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPServer.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPServer.o src/HTTPServer.cc + +${OBJECTDIR}/src/ConnectionPoint.o: nbproject/Makefile-${CND_CONF}.mk src/ConnectionPoint.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ConnectionPoint.o src/ConnectionPoint.cc + +${OBJECTDIR}/src/HTTPResponse.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPResponse.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPResponse.o src/HTTPResponse.cc + +${OBJECTDIR}/src/ConnectionHandler.o: nbproject/Makefile-${CND_CONF}.mk src/ConnectionHandler.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ConnectionHandler.o src/ConnectionHandler.cc + +${OBJECTDIR}/src/Credentials.o: nbproject/Makefile-${CND_CONF}.mk src/Credentials.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Credentials.o src/Credentials.cc + +${OBJECTDIR}/src/HTTPRequestHandler.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPRequestHandler.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPRequestHandler.o src/HTTPRequestHandler.cc + +${OBJECTDIR}/src/HTTPMessage.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPMessage.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPMessage.o src/HTTPMessage.cc + +${OBJECTDIR}/src/HTTPFileResponse.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPFileResponse.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPFileResponse.o src/HTTPFileResponse.cc + +${OBJECTDIR}/src/HTTPParser.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPParser.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPParser.o src/HTTPParser.cc + +${OBJECTDIR}/src/ClientSocket.o: nbproject/Makefile-${CND_CONF}.mk src/ClientSocket.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ClientSocket.o src/ClientSocket.cc + +${OBJECTDIR}/src/AbstractSocket.o: nbproject/Makefile-${CND_CONF}.mk src/AbstractSocket.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/AbstractSocket.o src/AbstractSocket.cc + +${OBJECTDIR}/src/HTTPStatus.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPStatus.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -g -Wall -D_GNU_SOURCE=1 -D_REENTRANT -Iinclude -I../util/include -I../vdr/include -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPStatus.o src/HTTPStatus.cc + +# Subprojects +.build-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r ${CND_BUILDDIR}/${CND_CONF} + ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + +# Subprojects +.clean-subprojects: + +# Enable dependency checking +.dep.inc: .depcheck-impl + +include .dep.inc diff --git a/libs/networking/nbproject/Makefile-Release.mk b/libs/networking/nbproject/Makefile-Release.mk new file mode 100644 index 0000000..39e0873 --- /dev/null +++ b/libs/networking/nbproject/Makefile-Release.mk @@ -0,0 +1,193 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a -pre and a -post target defined where you can add customized code. +# +# This makefile implements configuration specific macros and targets. + + +# Environment +MKDIR=mkdir +CP=cp +GREP=grep +NM=nm +CCADMIN=CCadmin +RANLIB=ranlib +CC=gcc +CCC=g++ +CXX=g++ +FC=gfortran +AS=as + +# Macros +CND_PLATFORM=GNU-Linux-x86 +CND_CONF=Release +CND_DISTDIR=dist +CND_BUILDDIR=build + +# Include project Makefile +include Makefile + +# Object Directory +OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM} + +# Object Files +OBJECTFILES= \ + ${OBJECTDIR}/src/HTTPRequest.o \ + ${OBJECTDIR}/src/ServerSocket.o \ + ${OBJECTDIR}/src/HTTPAuthorizationRequest.o \ + ${OBJECTDIR}/src/Url.o \ + ${OBJECTDIR}/src/Principal.o \ + ${OBJECTDIR}/src/Authorization.o \ + ${OBJECTDIR}/src/ServerConfig.o \ + ${OBJECTDIR}/src/HTTPServer.o \ + ${OBJECTDIR}/src/ConnectionPoint.o \ + ${OBJECTDIR}/src/HTTPResponse.o \ + ${OBJECTDIR}/src/ConnectionHandler.o \ + ${OBJECTDIR}/src/Credentials.o \ + ${OBJECTDIR}/src/HTTPRequestHandler.o \ + ${OBJECTDIR}/src/HTTPMessage.o \ + ${OBJECTDIR}/src/HTTPFileResponse.o \ + ${OBJECTDIR}/src/HTTPParser.o \ + ${OBJECTDIR}/src/ClientSocket.o \ + ${OBJECTDIR}/src/AbstractSocket.o \ + ${OBJECTDIR}/src/HTTPStatus.o + + +# C Compiler Flags +CFLAGS= + +# CC Compiler Flags +CCFLAGS= +CXXFLAGS= + +# Fortran Compiler Flags +FFLAGS= + +# Assembler Flags +ASFLAGS= + +# Link Libraries and Options +LDLIBSOPTIONS= + +# Build Targets +.build-conf: ${BUILD_SUBPROJECTS} + "${MAKE}" -f nbproject/Makefile-${CND_CONF}.mk ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + +${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a: ${OBJECTFILES} + ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} + ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + ${AR} -rv ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a ${OBJECTFILES} + $(RANLIB) ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + +${OBJECTDIR}/src/HTTPRequest.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPRequest.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPRequest.o src/HTTPRequest.cc + +${OBJECTDIR}/src/ServerSocket.o: nbproject/Makefile-${CND_CONF}.mk src/ServerSocket.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ServerSocket.o src/ServerSocket.cc + +${OBJECTDIR}/src/HTTPAuthorizationRequest.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPAuthorizationRequest.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPAuthorizationRequest.o src/HTTPAuthorizationRequest.cc + +${OBJECTDIR}/src/Url.o: nbproject/Makefile-${CND_CONF}.mk src/Url.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Url.o src/Url.cc + +${OBJECTDIR}/src/Principal.o: nbproject/Makefile-${CND_CONF}.mk src/Principal.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Principal.o src/Principal.cc + +${OBJECTDIR}/src/Authorization.o: nbproject/Makefile-${CND_CONF}.mk src/Authorization.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Authorization.o src/Authorization.cc + +${OBJECTDIR}/src/ServerConfig.o: nbproject/Makefile-${CND_CONF}.mk src/ServerConfig.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ServerConfig.o src/ServerConfig.cc + +${OBJECTDIR}/src/HTTPServer.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPServer.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPServer.o src/HTTPServer.cc + +${OBJECTDIR}/src/ConnectionPoint.o: nbproject/Makefile-${CND_CONF}.mk src/ConnectionPoint.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ConnectionPoint.o src/ConnectionPoint.cc + +${OBJECTDIR}/src/HTTPResponse.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPResponse.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPResponse.o src/HTTPResponse.cc + +${OBJECTDIR}/src/ConnectionHandler.o: nbproject/Makefile-${CND_CONF}.mk src/ConnectionHandler.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ConnectionHandler.o src/ConnectionHandler.cc + +${OBJECTDIR}/src/Credentials.o: nbproject/Makefile-${CND_CONF}.mk src/Credentials.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/Credentials.o src/Credentials.cc + +${OBJECTDIR}/src/HTTPRequestHandler.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPRequestHandler.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPRequestHandler.o src/HTTPRequestHandler.cc + +${OBJECTDIR}/src/HTTPMessage.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPMessage.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPMessage.o src/HTTPMessage.cc + +${OBJECTDIR}/src/HTTPFileResponse.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPFileResponse.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPFileResponse.o src/HTTPFileResponse.cc + +${OBJECTDIR}/src/HTTPParser.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPParser.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPParser.o src/HTTPParser.cc + +${OBJECTDIR}/src/ClientSocket.o: nbproject/Makefile-${CND_CONF}.mk src/ClientSocket.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/ClientSocket.o src/ClientSocket.cc + +${OBJECTDIR}/src/AbstractSocket.o: nbproject/Makefile-${CND_CONF}.mk src/AbstractSocket.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/AbstractSocket.o src/AbstractSocket.cc + +${OBJECTDIR}/src/HTTPStatus.o: nbproject/Makefile-${CND_CONF}.mk src/HTTPStatus.cc + ${MKDIR} -p ${OBJECTDIR}/src + ${RM} $@.d + $(COMPILE.cc) -O2 -MMD -MP -MF $@.d -o ${OBJECTDIR}/src/HTTPStatus.o src/HTTPStatus.cc + +# Subprojects +.build-subprojects: + +# Clean Targets +.clean-conf: ${CLEAN_SUBPROJECTS} + ${RM} -r ${CND_BUILDDIR}/${CND_CONF} + ${RM} ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a + +# Subprojects +.clean-subprojects: + +# Enable dependency checking +.dep.inc: .depcheck-impl + +include .dep.inc diff --git a/libs/networking/nbproject/Makefile-impl.mk b/libs/networking/nbproject/Makefile-impl.mk new file mode 100644 index 0000000..08c8342 --- /dev/null +++ b/libs/networking/nbproject/Makefile-impl.mk @@ -0,0 +1,133 @@ +# +# Generated Makefile - do not edit! +# +# Edit the Makefile in the project folder instead (../Makefile). Each target +# has a pre- and a post- target defined where you can add customization code. +# +# This makefile implements macros and targets common to all configurations. +# +# NOCDDL + + +# Building and Cleaning subprojects are done by default, but can be controlled with the SUB +# macro. If SUB=no, subprojects will not be built or cleaned. The following macro +# statements set BUILD_SUB-CONF and CLEAN_SUB-CONF to .build-reqprojects-conf +# and .clean-reqprojects-conf unless SUB has the value 'no' +SUB_no=NO +SUBPROJECTS=${SUB_${SUB}} +BUILD_SUBPROJECTS_=.build-subprojects +BUILD_SUBPROJECTS_NO= +BUILD_SUBPROJECTS=${BUILD_SUBPROJECTS_${SUBPROJECTS}} +CLEAN_SUBPROJECTS_=.clean-subprojects +CLEAN_SUBPROJECTS_NO= +CLEAN_SUBPROJECTS=${CLEAN_SUBPROJECTS_${SUBPROJECTS}} + + +# Project Name +PROJECTNAME=networking + +# Active Configuration +DEFAULTCONF=Debug +CONF=${DEFAULTCONF} + +# All Configurations +ALLCONFS=Debug Release + + +# build +.build-impl: .build-pre .validate-impl .depcheck-impl + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf + + +# clean +.clean-impl: .clean-pre .validate-impl .depcheck-impl + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf + + +# clobber +.clobber-impl: .clobber-pre .depcheck-impl + @#echo "=> Running $@..." + for CONF in ${ALLCONFS}; \ + do \ + "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .clean-conf; \ + done + +# all +.all-impl: .all-pre .depcheck-impl + @#echo "=> Running $@..." + for CONF in ${ALLCONFS}; \ + do \ + "${MAKE}" -f nbproject/Makefile-$${CONF}.mk QMAKE=${QMAKE} SUBPROJECTS=${SUBPROJECTS} .build-conf; \ + done + +# build tests +.build-tests-impl: .build-impl .build-tests-pre + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .build-tests-conf + +# run tests +.test-impl: .build-tests-impl .test-pre + @#echo "=> Running $@... Configuration=$(CONF)" + "${MAKE}" -f nbproject/Makefile-${CONF}.mk SUBPROJECTS=${SUBPROJECTS} .test-conf + +# dependency checking support +.depcheck-impl: + @echo "# This code depends on make tool being used" >.dep.inc + @if [ -n "${MAKE_VERSION}" ]; then \ + echo "DEPFILES=\$$(wildcard \$$(addsuffix .d, \$${OBJECTFILES}))" >>.dep.inc; \ + echo "ifneq (\$${DEPFILES},)" >>.dep.inc; \ + echo "include \$${DEPFILES}" >>.dep.inc; \ + echo "endif" >>.dep.inc; \ + else \ + echo ".KEEP_STATE:" >>.dep.inc; \ + echo ".KEEP_STATE_FILE:.make.state.\$${CONF}" >>.dep.inc; \ + fi + +# configuration validation +.validate-impl: + @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \ + then \ + echo ""; \ + echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \ + echo "See 'make help' for details."; \ + echo "Current directory: " `pwd`; \ + echo ""; \ + fi + @if [ ! -f nbproject/Makefile-${CONF}.mk ]; \ + then \ + exit 1; \ + fi + + +# help +.help-impl: .help-pre + @echo "This makefile supports the following configurations:" + @echo " ${ALLCONFS}" + @echo "" + @echo "and the following targets:" + @echo " build (default target)" + @echo " clean" + @echo " clobber" + @echo " all" + @echo " help" + @echo "" + @echo "Makefile Usage:" + @echo " make [CONF=<CONFIGURATION>] [SUB=no] build" + @echo " make [CONF=<CONFIGURATION>] [SUB=no] clean" + @echo " make [SUB=no] clobber" + @echo " make [SUB=no] all" + @echo " make help" + @echo "" + @echo "Target 'build' will build a specific configuration and, unless 'SUB=no'," + @echo " also build subprojects." + @echo "Target 'clean' will clean a specific configuration and, unless 'SUB=no'," + @echo " also clean subprojects." + @echo "Target 'clobber' will remove all built files from all configurations and," + @echo " unless 'SUB=no', also from subprojects." + @echo "Target 'all' will will build all configurations and, unless 'SUB=no'," + @echo " also build subprojects." + @echo "Target 'help' prints this message." + @echo "" + diff --git a/libs/networking/nbproject/Makefile-variables.mk b/libs/networking/nbproject/Makefile-variables.mk new file mode 100644 index 0000000..25db304 --- /dev/null +++ b/libs/networking/nbproject/Makefile-variables.mk @@ -0,0 +1,35 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +CND_BASEDIR=`pwd` +CND_BUILDDIR=build +CND_DISTDIR=dist +# Debug configuration +CND_PLATFORM_Debug=GNU-Linux-x86 +CND_ARTIFACT_DIR_Debug=dist/Debug/GNU-Linux-x86 +CND_ARTIFACT_NAME_Debug=libnetworking.a +CND_ARTIFACT_PATH_Debug=dist/Debug/GNU-Linux-x86/libnetworking.a +CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux-x86/package +CND_PACKAGE_NAME_Debug=networking.tar +CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/networking.tar +# Release configuration +CND_PLATFORM_Release=GNU-Linux-x86 +CND_ARTIFACT_DIR_Release=dist/Release/GNU-Linux-x86 +CND_ARTIFACT_NAME_Release=libnetworking.a +CND_ARTIFACT_PATH_Release=dist/Release/GNU-Linux-x86/libnetworking.a +CND_PACKAGE_DIR_Release=dist/Release/GNU-Linux-x86/package +CND_PACKAGE_NAME_Release=networking.tar +CND_PACKAGE_PATH_Release=dist/Release/GNU-Linux-x86/package/networking.tar +# +# include compiler specific variables +# +# dmake command +ROOT:sh = test -f nbproject/private/Makefile-variables.mk || \ + (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk) +# +# gmake command +.PHONY: $(shell test -f nbproject/private/Makefile-variables.mk || (mkdir -p nbproject/private && touch nbproject/private/Makefile-variables.mk)) +# +include nbproject/private/Makefile-variables.mk diff --git a/libs/networking/nbproject/Package-Debug.bash b/libs/networking/nbproject/Package-Debug.bash new file mode 100644 index 0000000..4c7fd47 --- /dev/null +++ b/libs/networking/nbproject/Package-Debug.bash @@ -0,0 +1,75 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_PLATFORM=GNU-Linux-x86 +CND_CONF=Debug +CND_DISTDIR=dist +CND_BUILDDIR=build +NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a +OUTPUT_BASENAME=libnetworking.a +PACKAGE_TOP_DIR=networking/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package +rm -rf ${NBTMPDIR} +mkdir -p ${NBTMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory "${NBTMPDIR}/networking/lib" +copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}lib/${OUTPUT_BASENAME}" 0644 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/networking.tar +cd ${NBTMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/networking.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${NBTMPDIR} diff --git a/libs/networking/nbproject/Package-Release.bash b/libs/networking/nbproject/Package-Release.bash new file mode 100644 index 0000000..4525cc6 --- /dev/null +++ b/libs/networking/nbproject/Package-Release.bash @@ -0,0 +1,75 @@ +#!/bin/bash -x + +# +# Generated - do not edit! +# + +# Macros +TOP=`pwd` +CND_PLATFORM=GNU-Linux-x86 +CND_CONF=Release +CND_DISTDIR=dist +CND_BUILDDIR=build +NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging +TMPDIRNAME=tmp-packaging +OUTPUT_PATH=${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/libnetworking.a +OUTPUT_BASENAME=libnetworking.a +PACKAGE_TOP_DIR=networking/ + +# Functions +function checkReturnCode +{ + rc=$? + if [ $rc != 0 ] + then + exit $rc + fi +} +function makeDirectory +# $1 directory path +# $2 permission (optional) +{ + mkdir -p "$1" + checkReturnCode + if [ "$2" != "" ] + then + chmod $2 "$1" + checkReturnCode + fi +} +function copyFileToTmpDir +# $1 from-file path +# $2 to-file path +# $3 permission +{ + cp "$1" "$2" + checkReturnCode + if [ "$3" != "" ] + then + chmod $3 "$2" + checkReturnCode + fi +} + +# Setup +cd "${TOP}" +mkdir -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package +rm -rf ${NBTMPDIR} +mkdir -p ${NBTMPDIR} + +# Copy files and create directories and links +cd "${TOP}" +makeDirectory "${NBTMPDIR}/networking/lib" +copyFileToTmpDir "${OUTPUT_PATH}" "${NBTMPDIR}/${PACKAGE_TOP_DIR}lib/${OUTPUT_BASENAME}" 0644 + + +# Generate tar file +cd "${TOP}" +rm -f ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/networking.tar +cd ${NBTMPDIR} +tar -vcf ../../../../${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/package/networking.tar * +checkReturnCode + +# Cleanup +cd "${TOP}" +rm -rf ${NBTMPDIR} diff --git a/libs/networking/nbproject/configurations.xml b/libs/networking/nbproject/configurations.xml new file mode 100644 index 0000000..fc79ca1 --- /dev/null +++ b/libs/networking/nbproject/configurations.xml @@ -0,0 +1,114 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configurationDescriptor version="80"> + <logicalFolder name="root" displayName="root" projectFiles="true" kind="ROOT"> + <logicalFolder name="HeaderFiles" + displayName="Header Files" + projectFiles="true"> + <itemPath>include/AbstractSocket.h</itemPath> + <itemPath>include/Authorization.h</itemPath> + <itemPath>include/ClientSocket.h</itemPath> + <itemPath>include/ConnectionHandler.h</itemPath> + <itemPath>include/ConnectionPoint.h</itemPath> + <itemPath>include/Credentials.h</itemPath> + <itemPath>include/HTTPAuthorizationRequest.h</itemPath> + <itemPath>include/HTTPFileResponse.h</itemPath> + <itemPath>include/HTTPMessage.h</itemPath> + <itemPath>include/HTTPParser.h</itemPath> + <itemPath>include/HTTPRequest.h</itemPath> + <itemPath>include/HTTPRequestHandler.h</itemPath> + <itemPath>include/HTTPResponse.h</itemPath> + <itemPath>include/HTTPServer.h</itemPath> + <itemPath>include/HTTPStatus.h</itemPath> + <itemPath>include/Principal.h</itemPath> + <itemPath>include/ServerConfig.h</itemPath> + <itemPath>include/ServerSocket.h</itemPath> + <itemPath>include/Url.h</itemPath> + </logicalFolder> + <logicalFolder name="ResourceFiles" + displayName="Resource Files" + projectFiles="true"> + </logicalFolder> + <logicalFolder name="SourceFiles" + displayName="Source Files" + projectFiles="true"> + <itemPath>src/AbstractSocket.cc</itemPath> + <itemPath>src/Authorization.cc</itemPath> + <itemPath>src/ClientSocket.cc</itemPath> + <itemPath>src/ConnectionHandler.cc</itemPath> + <itemPath>src/ConnectionPoint.cc</itemPath> + <itemPath>src/Credentials.cc</itemPath> + <itemPath>src/HTTPAuthorizationRequest.cc</itemPath> + <itemPath>src/HTTPFileResponse.cc</itemPath> + <itemPath>src/HTTPMessage.cc</itemPath> + <itemPath>src/HTTPParser.cc</itemPath> + <itemPath>src/HTTPRequest.cc</itemPath> + <itemPath>src/HTTPRequestHandler.cc</itemPath> + <itemPath>src/HTTPResponse.cc</itemPath> + <itemPath>src/HTTPServer.cc</itemPath> + <itemPath>src/HTTPStatus.cc</itemPath> + <itemPath>src/Principal.cc</itemPath> + <itemPath>src/ServerConfig.cc</itemPath> + <itemPath>src/ServerSocket.cc</itemPath> + <itemPath>src/Url.cc</itemPath> + </logicalFolder> + <logicalFolder name="TestFiles" + displayName="Test Files" + projectFiles="false" + kind="TEST_LOGICAL_FOLDER"> + </logicalFolder> + <logicalFolder name="ExternalFiles" + displayName="Important Files" + projectFiles="false" + kind="IMPORTANT_FILES_FOLDER"> + <itemPath>Makefile</itemPath> + </logicalFolder> + </logicalFolder> + <projectmakefile>Makefile</projectmakefile> + <confs> + <conf name="Debug" type="3"> + <toolsSet> + <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode> + <compilerSet>default</compilerSet> + </toolsSet> + <compileType> + <ccTool> + <incDir> + <pElem>include</pElem> + <pElem>../util/include</pElem> + <pElem>../vdr/include</pElem> + </incDir> + <commandLine>-std=gnu++0x -fomit-frame-pointer -fPIC -pthread -Wall -Wno-parentheses -Wno-switch -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wtype-limits -Wundef -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -ansi</commandLine> + <preprocessorList> + <Elem>_GNU_SOURCE=1</Elem> + <Elem>_REENTRANT</Elem> + </preprocessorList> + <warningLevel>2</warningLevel> + </ccTool> + <archiverTool> + </archiverTool> + </compileType> + </conf> + <conf name="Release" type="3"> + <toolsSet> + <remote-sources-mode>LOCAL_SOURCES</remote-sources-mode> + <compilerSet>default</compilerSet> + </toolsSet> + <compileType> + <cTool> + <developmentMode>5</developmentMode> + </cTool> + <ccTool> + <developmentMode>5</developmentMode> + </ccTool> + <fortranCompilerTool> + <developmentMode>5</developmentMode> + </fortranCompilerTool> + <asmTool> + <developmentMode>5</developmentMode> + </asmTool> + <archiverTool> + </archiverTool> + </compileType> + </conf> + </confs> +</configurationDescriptor> diff --git a/libs/networking/nbproject/private/Makefile-variables.mk b/libs/networking/nbproject/private/Makefile-variables.mk new file mode 100644 index 0000000..a64183e --- /dev/null +++ b/libs/networking/nbproject/private/Makefile-variables.mk @@ -0,0 +1,7 @@ +# +# Generated - do not edit! +# +# NOCDDL +# +# Debug configuration +# Release configuration diff --git a/libs/networking/nbproject/private/configurations.xml b/libs/networking/nbproject/private/configurations.xml new file mode 100644 index 0000000..fa15dc7 --- /dev/null +++ b/libs/networking/nbproject/private/configurations.xml @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8"?> +<configurationDescriptor version="80"> + <projectmakefile>Makefile</projectmakefile> + <confs> + <conf name="Debug" type="3"> + <toolsSet> + <developmentServer>localhost</developmentServer> + <platform>2</platform> + </toolsSet> + <dbx_gdbdebugger version="1"> + <gdb_pathmaps> + </gdb_pathmaps> + <gdb_interceptlist> + <gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/> + </gdb_interceptlist> + <gdb_options> + <DebugOptions> + </DebugOptions> + </gdb_options> + <gdb_buildfirst gdb_buildfirst_overriden="false" gdb_buildfirst_old="false"/> + </dbx_gdbdebugger> + <nativedebugger version="1"> + <engine>gdb</engine> + </nativedebugger> + <runprofile version="9"> + <runcommandpicklist> + <runcommandpicklistitem>"${OUTPUT_PATH}"</runcommandpicklistitem> + </runcommandpicklist> + <runcommand>"${OUTPUT_PATH}"</runcommand> + <rundir></rundir> + <buildfirst>true</buildfirst> + <terminal-type>0</terminal-type> + <remove-instrumentation>0</remove-instrumentation> + <environment> + </environment> + </runprofile> + </conf> + <conf name="Release" type="3"> + <toolsSet> + <developmentServer>localhost</developmentServer> + <platform>2</platform> + </toolsSet> + <dbx_gdbdebugger version="1"> + <gdb_pathmaps> + </gdb_pathmaps> + <gdb_interceptlist> + <gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/> + </gdb_interceptlist> + <gdb_options> + <DebugOptions> + </DebugOptions> + </gdb_options> + <gdb_buildfirst gdb_buildfirst_overriden="false" gdb_buildfirst_old="false"/> + </dbx_gdbdebugger> + <nativedebugger version="1"> + <engine>gdb</engine> + </nativedebugger> + <runprofile version="9"> + <runcommandpicklist> + <runcommandpicklistitem>"${OUTPUT_PATH}"</runcommandpicklistitem> + </runcommandpicklist> + <runcommand>"${OUTPUT_PATH}"</runcommand> + <rundir></rundir> + <buildfirst>true</buildfirst> + <terminal-type>0</terminal-type> + <remove-instrumentation>0</remove-instrumentation> + <environment> + </environment> + </runprofile> + </conf> + </confs> +</configurationDescriptor> diff --git a/libs/networking/nbproject/private/private.xml b/libs/networking/nbproject/private/private.xml new file mode 100644 index 0000000..5ee2703 --- /dev/null +++ b/libs/networking/nbproject/private/private.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project-private xmlns="http://www.netbeans.org/ns/project-private/1"> + <data xmlns="http://www.netbeans.org/ns/make-project-private/1"> + <activeConfTypeElem>3</activeConfTypeElem> + <activeConfIndexElem>0</activeConfIndexElem> + </data> + <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/1"/> +</project-private> diff --git a/libs/networking/nbproject/project.xml b/libs/networking/nbproject/project.xml new file mode 100644 index 0000000..45ed83d --- /dev/null +++ b/libs/networking/nbproject/project.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://www.netbeans.org/ns/project/1"> + <type>org.netbeans.modules.cnd.makeproject</type> + <configuration> + <data xmlns="http://www.netbeans.org/ns/make-project/1"> + <name>networking</name> + <c-extensions/> + <cpp-extensions>cc</cpp-extensions> + <header-extensions>h</header-extensions> + <sourceEncoding>UTF-8</sourceEncoding> + <make-dep-projects/> + <sourceRootList/> + <confList> + <confElem> + <name>Debug</name> + <type>3</type> + </confElem> + <confElem> + <name>Release</name> + <type>3</type> + </confElem> + </confList> + </data> + </configuration> +</project> diff --git a/libs/networking/networking.cbp b/libs/networking/networking.cbp new file mode 100644 index 0000000..fc36817 --- /dev/null +++ b/libs/networking/networking.cbp @@ -0,0 +1,88 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_project_file> + <FileVersion major="1" minor="6" /> + <Project> + <Option title="CMP.libs.networking" /> + <Option pch_mode="2" /> + <Option compiler="gcc" /> + <Build> + <Target title="Debug"> + <Option output="libnetworking" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="obj/Debug/" /> + <Option type="2" /> + <Option compiler="gcc" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-Wall" /> + <Add option="-g" /> + </Compiler> + </Target> + <Target title="Release"> + <Option output="libnetworking" prefix_auto="1" extension_auto="1" /> + <Option working_dir="" /> + <Option object_output="obj/Release/" /> + <Option type="2" /> + <Option compiler="gcc" /> + <Option createDefFile="1" /> + <Compiler> + <Add option="-Wall" /> + <Add option="-O2" /> + </Compiler> + <Linker> + <Add option="-s" /> + </Linker> + </Target> + </Build> + <Compiler> + <Add option="-std=gnu++0x -fomit-frame-pointer -fPIC -pthread -Wall -Wno-parentheses -Wno-switch -Wdisabled-optimization -Wpointer-arith -Wredundant-decls -Wwrite-strings -Wtype-limits -Wundef -fno-math-errno -fno-signed-zeros -fno-tree-vectorize -Werror=implicit-function-declaration -ansi" /> + <Add option="-D_REENTRANT" /> + <Add option="-D_GNU_SOURCE=1" /> + <Add directory="../vdr/include" /> + <Add directory="../util/include" /> + <Add directory="include" /> + </Compiler> + <Unit filename="include/AbstractSocket.h" /> + <Unit filename="include/Authorization.h" /> + <Unit filename="include/ClientSocket.h" /> + <Unit filename="include/ConnectionHandler.h" /> + <Unit filename="include/ConnectionPoint.h" /> + <Unit filename="include/Credentials.h" /> + <Unit filename="include/HTTPAuthorizationRequest.h" /> + <Unit filename="include/HTTPFileResponse.h" /> + <Unit filename="include/HTTPMessage.h" /> + <Unit filename="include/HTTPRequest.h" /> + <Unit filename="include/HTTPRequestHandler.h" /> + <Unit filename="include/HTTPResponse.h" /> + <Unit filename="include/HTTPServer.h" /> + <Unit filename="include/HTTPStatus.h" /> + <Unit filename="include/Principal.h" /> + <Unit filename="include/ServerConfig.h" /> + <Unit filename="include/ServerSocket.h" /> + <Unit filename="include/Url.h" /> + <Unit filename="src/AbstractSocket.cc" /> + <Unit filename="src/Authorization.cc" /> + <Unit filename="src/ClientSocket.cc" /> + <Unit filename="src/ConnectionHandler.cc" /> + <Unit filename="src/ConnectionPoint.cc" /> + <Unit filename="src/Credentials.cc" /> + <Unit filename="src/HTTPAuthorizationRequest.cc" /> + <Unit filename="src/HTTPFileResponse.cc" /> + <Unit filename="src/HTTPMessage.cc" /> + <Unit filename="src/HTTPRequest.cc" /> + <Unit filename="src/HTTPRequestHandler.cc" /> + <Unit filename="src/HTTPResponse.cc" /> + <Unit filename="src/HTTPServer.cc" /> + <Unit filename="src/HTTPStatus.cc" /> + <Unit filename="src/Principal.cc" /> + <Unit filename="src/ServerConfig.cc" /> + <Unit filename="src/ServerSocket.cc" /> + <Unit filename="src/Url.cc" /> + <Extensions> + <code_completion /> + <envvars /> + <lib_finder disable_auto="1" /> + <debugger /> + </Extensions> + </Project> +</CodeBlocks_project_file> diff --git a/libs/networking/networking.depend b/libs/networking/networking.depend new file mode 100644 index 0000000..c4ac310 --- /dev/null +++ b/libs/networking/networking.depend @@ -0,0 +1 @@ +# depslib dependency file v1.0 diff --git a/libs/networking/networking.layout b/libs/networking/networking.layout new file mode 100644 index 0000000..a008101 --- /dev/null +++ b/libs/networking/networking.layout @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_layout_file> + <ActiveTarget name="Debug" /> + <File name="src/HTTPFileResponse.cc" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="src/ConnectionHandler.cc" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1551" topLine="0" /> + </Cursor> + </File> + <File name="src/ConnectionPoint.cc" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/HTTPMessage.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/ConnectionHandler.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/ConnectionPoint.h" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="src/HTTPMessage.cc" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/HTTPResponse.h" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> +</CodeBlocks_layout_file> diff --git a/libs/networking/networking.layout.save b/libs/networking/networking.layout.save new file mode 100644 index 0000000..e313395 --- /dev/null +++ b/libs/networking/networking.layout.save @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> +<CodeBlocks_layout_file> + <ActiveTarget name="Debug" /> + <File name="src/ConnectionPoint.cc" open="0" top="0" tabpos="4" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/HTTPMessage.h" open="0" top="0" tabpos="7" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="src/HTTPMessage.cc" open="0" top="0" tabpos="8" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="src/HTTPFileResponse.cc" open="0" top="0" tabpos="3" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/HTTPResponse.h" open="0" top="0" tabpos="5" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/ConnectionPoint.h" open="0" top="0" tabpos="6" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="include/ConnectionHandler.h" open="0" top="0" tabpos="2" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="0" topLine="0" /> + </Cursor> + </File> + <File name="src/ConnectionHandler.cc" open="0" top="0" tabpos="1" split="0" active="1" splitpos="0" zoom_1="0" zoom_2="0"> + <Cursor> + <Cursor1 position="1551" topLine="0" /> + </Cursor> + </File> +</CodeBlocks_layout_file> diff --git a/libs/networking/poll.sample b/libs/networking/poll.sample new file mode 100644 index 0000000..a252b7d --- /dev/null +++ b/libs/networking/poll.sample @@ -0,0 +1,53 @@ +EXAMPLES + + Checking for Events on a Stream + + The following example opens a pair of STREAMS devices and then waits for either one to become writable. This example proceeds as follows: + + 1. Sets the timeout parameter to 500 milliseconds. + 2. Opens the STREAMS devices /dev/dev0 and /dev/dev1, and then polls them, specifying POLLOUT and POLLWRBAND as the events of interest. + The STREAMS device names /dev/dev0 and /dev/dev1 are only examples of how STREAMS devices can be named; STREAMS naming conventions may vary among systems conforming to the IEEE Std 1003.1-2001. + 3. Uses the ret variable to determine whether an event has occurred on either of the two STREAMS. The poll() function is given 500 milliseconds to wait for an event to occur (if it has not occurred prior to the poll() call). + 4. Checks the returned value of ret. If a positive value is returned, one of the following can be done: + 1. Priority data can be written to the open STREAM on priority bands greater than 0, because the POLLWRBAND event occurred on the open STREAM ( fds[0] or fds[1]). + 2. Data can be written to the open STREAM on priority-band 0, because the POLLOUT event occurred on the open STREAM ( fds[0] or fds[1]). + 5. If the returned value is not a positive value, permission to write data to the open STREAM (on any priority band) is denied. + 6. If the POLLHUP event occurs on the open STREAM ( fds[0] or fds[1]), the device on the open STREAM has disconnected. + + #include <stropts.h> + #include <poll.h> + ... + struct pollfd fds[2]; + int timeout_msecs = 500; + int ret; + int i; + + + /* Open STREAMS device. */ + fds[0].fd = open("/dev/dev0", ...); + fds[1].fd = open("/dev/dev1", ...); + fds[0].events = POLLOUT | POLLWRBAND; + fds[1].events = POLLOUT | POLLWRBAND; + + + ret = poll(fds, 2, timeout_msecs); + + + if (ret > 0) { + /* An event on one of the fds has occurred. */ + for (i=0; i<2; i++) { + if (fds[i].revents & POLLWRBAND) { + /* Priority data may be written on device number i. */ + ... + } + if (fds[i].revents & POLLOUT) { + /* Data may be written on device number i. */ + ... + } + if (fds[i].revents & POLLHUP) { + /* A hangup has occurred on device number i. */ + ... + } + } + } + diff --git a/libs/networking/src/AbstractSocket.cc b/libs/networking/src/AbstractSocket.cc new file mode 100644 index 0000000..827d466 --- /dev/null +++ b/libs/networking/src/AbstractSocket.cc @@ -0,0 +1,290 @@ +/** + * ======================== legal notice ====================== + * + * File: AbstractSocket.cc + * Created: 4. Juli 2012, 07:13 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <AbstractSocket.h> +#include <Logging.h> +#include <stddef.h> +#include <arpa/inet.h> +#include <resolv.h> +#include <netdb.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <poll.h> + +cAbstractSocket::cAbstractSocket(int Port, int Queue) + : sock(-1) + , queue(Queue) + , blocking(true) + , thisSide(NULL) +{ +} + +cAbstractSocket::cAbstractSocket(const char *ServerName, int Port) + : sock(-1) + , queue(0) + , blocking(true) + , thisSide(NULL) +{ + others.push_back(new cConnectionPoint(ServerName, Port)); +} + +cAbstractSocket::~cAbstractSocket() +{ + Close(); + if (thisSide) delete thisSide; + cConnectionPoint *p; + + for (size_t i=0; i < others.size(); ++i) { + p = others[i]; + delete p; + } +} + +void cAbstractSocket::Close(void) +{ + if (sock >= 0) { + close(sock); + sock = -1; + } +} + +// the client side +bool cAbstractSocket::Connect(void) +{ + if (sock < 0) { + struct addrinfo hints, *result, *rp; + char buf[20]; + int s; + + /* Obtain address(es) matching host/port */ + memset(buf, 0, sizeof(buf)); + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_UNSPEC; // Allow IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; + snprintf(buf, sizeof(buf), "%d", OtherSide()->Port()); + + if ((s = getaddrinfo(OtherSide()->HostName(), buf, &hints, &result))) { + esyslog("getaddrinfo: %s", gai_strerror(s)); + + return -1; + } + + // getaddrinfo potentially returns a list of addresses, that may fit, + // so try each address until we successfully connect + for (rp = result; rp; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1) continue; + + if (connect(sock, rp->ai_addr, rp->ai_addrlen) != -1) + break; // we got a connection + close(sock); + } + if (rp == NULL) { // no address could be connected to + esyslog("Could not connect!"); + Close(); + + return false; + } + // here we have a valid connection, so lets gather some information + thisSide = GetNameAndAddress(sock, rp->ai_addr, rp->ai_addrlen); + OtherSide()->SetSocket(sock); + char nameBuf[512]; + + memset(nameBuf, 0, sizeof(nameBuf)); + if ((s = getnameinfo(rp->ai_addr, rp->ai_addrlen, nameBuf, sizeof(nameBuf), NULL, 0, NI_NAMEREQD))) { + esyslog("failed to determine servers hostname %s", gai_strerror(s)); + } + else { + OtherSide()->SetRealName(nameBuf); + } + freeaddrinfo(result); + } + return sock > 0; +} + +// as each address may be IP4 or IP6, cut this off +static void * getAddr(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) + return &(((struct sockaddr_in*)sa)->sin_addr); + return &(((struct sockaddr_in6*)sa)->sin6_addr); +} + +// same is true for port access +static int getPort(struct sockaddr *sa) +{ + if (sa->sa_family == AF_INET) + return ((struct sockaddr_in*)sa)->sin_port; + return ((struct sockaddr_in6*)sa)->sin6_port; +} + +cConnectionPoint *cAbstractSocket::GetNameAndAddress(int Socket, struct sockaddr *sa, socklen_t sa_size) +{ + cConnectionPoint *rv = NULL; + char nameBuf[512], addrBuf[INET6_ADDRSTRLEN]; + + if (getnameinfo(sa, sa_size, nameBuf, sizeof(nameBuf), NULL, 0, NI_NAMEREQD)) { + // ok, just ip address has to suffice to start work + rv = new cConnectionPoint(inet_ntop(sa->sa_family, getAddr(sa), addrBuf, sizeof(addrBuf)) + , ntohs(getPort(sa)) + , inet_ntop(sa->sa_family, getAddr(sa), addrBuf, sizeof(addrBuf))); + } + else { + rv = new cConnectionPoint(inet_ntop(sa->sa_family, getAddr(sa), addrBuf, sizeof(addrBuf)) + , ntohs(getPort(sa)) + , nameBuf); + } + if (rv) rv->SetSocket(Socket); + + return rv; +} + +void cAbstractSocket::SetBlockingIO(bool ForceBlockingIO) +{ + blocking = ForceBlockingIO; +} + +// server side first part +bool cAbstractSocket::Open(int Port) +{ + if (sock < 0) { + isyslog("socket is < 0 - so start a new connection ..."); + struct addrinfo hints, *result, *rp; + char buf[20]; + int s; + + memset(&hints, 0, sizeof(hints)); + memset(buf, 0, sizeof(buf)); + hints.ai_family = AF_UNSPEC; // allow IPv4 or IPv6 + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + snprintf(buf, sizeof(buf), "%d", Port); + + if ((s = getaddrinfo(NULL, buf, &hints, &result))) { + esyslog("getaddrinfo: %s\n", gai_strerror(s)); + + return false; + } + int yes=1; + + // getaddrinfo potentially returns a list of addresses, that may fit, + // so try each address until we successfully bound + for (rp = result; rp; rp = rp->ai_next) { + sock = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + if (sock == -1) continue; + + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)); + + if (bind(sock, rp->ai_addr, rp->ai_addrlen) != -1) + break; // ok, we succeeded to bind + close(sock); + } + if (!rp) { + esyslog("could not bind"); + Close(); + + return false; + } + ConfigureSocket(sock); + freeaddrinfo(result); + + // listen to the socket: + if (listen(sock, queue) < 0) { + esyslog("failed to listen to bound socket!"); + Close(); + return (false); + } + } + return (true); +} + +// server side second part +cConnectionPoint *cAbstractSocket::Accept(int Port, int TimeoutMs) +{ + cConnectionPoint *client = NULL; + + if (Open(Port)) { + struct sockaddr_storage clientname; + uint cl_size = sizeof(clientname); + struct pollfd pf[1]; + + pf[0].fd = sock; + pf[0].events = POLLIN; + + if (poll(pf, 1, TimeoutMs) < 1) return NULL; + int newsock = accept(sock, (struct sockaddr *) &clientname, &cl_size); + + if (newsock > 0) { + isyslog("ok, got client connection request ..."); + + // if server address has not been restricted at bind-time, its possible that we don't + // have a local address yet. If server is bound to 0 (any address), we can determine + // the real server address in use now. But only do it once. + if (!thisSide) { + struct sockaddr_storage server; + uint sa_size = sizeof(server); + + if (getpeername(newsock, (struct sockaddr *) &server, &sa_size)) { + esyslog("getpeername failed: #%d", errno); + } + else thisSide = GetNameAndAddress(newsock, (struct sockaddr *) &server, sa_size); + } + + // At server side, multiple clients can have open connections at the same time, + // so get rid of that here. We always fetch connections informations + // before any access decisions, so those could be extended to use names + // some day ... + client = GetNameAndAddress(newsock, (struct sockaddr *) &clientname, cl_size); + if (client) { + bool accepted = true; + //FIXME: change determination of accepting client access! + // accepted = SVDRPhosts.Acceptable(clientname.sin_addr.s_addr); + // change to: + // accepted = SVDRPHosts.Acceptable(cpi); + // so in SVDRPHosts you have IP-Address and real name (if accessible) + + if (!accepted) { + const char *s = "Access denied!\n"; + + if (write(newsock, s, strlen(s)) < 0) { + esyslog(s); + close(newsock); + } + newsock = -1; + client = NULL; + } + else { + others.push_back(client); + } + isyslog("connect from %s, port %hu - %s", client->HostName(), client->Port(), accepted ? "accepted" : "DENIED"); + } + } + else if (errno != EINTR && errno != EAGAIN) { + esyslog("failed to accept client"); + } + } + return (client); +} diff --git a/libs/networking/src/Authorization.cc b/libs/networking/src/Authorization.cc new file mode 100644 index 0000000..b22145a --- /dev/null +++ b/libs/networking/src/Authorization.cc @@ -0,0 +1,469 @@ +/** + * ======================== legal notice ====================== + * + * File: Authorization.cc + * Created: 3. Juli 2012, 17:27 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <Authorization.h> +#include <Credentials.h> +#include <MD5Calculator.h> +#include <Principal.h> +#include <ConnectionPoint.h> +#include <Logging.h> +#include <stdio.h> +#include <util.h> + +static bool useSessionHash = true; + +cAuthorization::cAuthorization(const cHTTPRequest &OriginalRequest, char *NOnceFromHeap) +///< use this constructor to create an authorization request for responses to +///< clients without valid authorization headers. + : tmp(NULL) + , principal(NULL) + , method(OriginalRequest.Method()) + , serverID(NULL) + , sessAlgo(useSessionHash) + , nonce(NOnceFromHeap) + , uri(OriginalRequest.Url().ToString()) + , response(NULL) + , opaque(NULL) + , cnonce(NULL) + , qop(NULL) + , counter(0) + , authTime(time(NULL)) +{ + tmp = new cPrincipal("unset", Credentials.ApplicationRealm()); + opaque = cAuthorizations::CreateSessionID(OriginalRequest, authTime); +} + +cAuthorization::cAuthorization(cHTTPRequest::HTTPRequestMethod Method, const char *Raw) +///< use this constructor to create an authorization from clients request message + : tmp(NULL) + , principal(NULL) + , method(Method) + , serverID(NULL) + , sessAlgo(false) + , nonce(NULL) + , uri(NULL) + , response(NULL) + , opaque(NULL) + , cnonce(NULL) + , qop(NULL) + , counter(0) +{ + ParseRawBuffer(Raw); +} + +cAuthorization::cAuthorization(const cPrincipal *Principal, cHTTPRequest::HTTPRequestMethod Method, const cAuthorization &other) + : tmp(other.tmp ? new cPrincipal(*other.tmp) : NULL) + , principal(Principal) + , method(Method) + , serverID(other.serverID ? strdup(other.serverID) : NULL) + , sessAlgo(other.sessAlgo) + , nonce(other.nonce ? strdup(other.nonce) : NULL) + , uri(other.uri ? strdup(other.uri) : NULL) + , response(other.response ? strdup(other.response) : NULL) + , opaque(other.opaque ? strdup(other.opaque) : NULL) + , cnonce(other.cnonce ? strdup(other.cnonce) : NULL) + , qop(other.qop ? strdup(other.qop) : NULL) + , counter(other.counter) +{ +} + +cAuthorization::cAuthorization(const cAuthorization& other) + : tmp(other.tmp ? new cPrincipal(*other.tmp) : NULL) + , principal(other.principal) + , method(other.method) + , serverID(other.serverID ? strdup(other.serverID) : NULL) + , sessAlgo(other.sessAlgo) + , nonce(other.nonce ? strdup(other.nonce) : NULL) + , uri(other.uri ? strdup(other.uri) : NULL) + , response(other.response ? strdup(other.response) : NULL) + , opaque(other.opaque ? strdup(other.opaque) : NULL) + , cnonce(other.cnonce ? strdup(other.cnonce) : NULL) + , qop(other.qop ? strdup(other.qop) : NULL) + , counter(other.counter + 1) +{ +} + +cAuthorization::~cAuthorization() +{ + if (tmp) delete tmp; + FREE(nonce); + FREE(uri); + FREE(serverID); + FREE(response); + FREE(opaque); + FREE(cnonce); + FREE(qop); +} + +cAuthorization& cAuthorization::operator=(const cAuthorization& other) +{ + if (&other == this) return *this; + if (tmp) delete tmp; + FREE(nonce); + FREE(uri); + FREE(serverID); + FREE(response); + FREE(opaque); + FREE(cnonce); + + principal = other.principal; + sessAlgo = other.sessAlgo; + method = other.method; + serverID = other.serverID ? strdup(other.serverID) : NULL; + nonce = other.nonce ? strdup(other.nonce) : NULL; + uri = other.uri ? strdup(other.uri) : NULL; + response = other.response ? strdup(other.response) : NULL; + opaque = other.opaque ? strdup(other.opaque) : NULL; + cnonce = other.cnonce ? strdup(other.cnonce) : NULL; + counter = other.counter; + qop = other.qop ? strdup(other.qop) : NULL; + tmp = other.tmp ? new cPrincipal(*other.tmp) : NULL; + + return *this; +} + +void cAuthorization::CreateClientHash() +{ + cMD5Calculator hc; + char buf[40]; + + snprintf(buf, sizeof(buf), "%lu", random()); + + hc.AddContent(serverID); + hc.AddContent(":"); + hc.AddContent(buf); + + cnonce = hc.Hash(); +} + +static const char *getAttrName(char *buf, int bufSize, const char *src) +{ + const char *s = src; + char *d = buf; + + while (*s && isspace(*s)) ++s; + while (*s && ((d - buf) < bufSize) && *s != '=' && !isspace(*s)) *d++ = *s++; + *d = 0; + + return *s ? s : NULL; +} + +static const char *getValue(char *buf, int bufSize, const char *src) +{ + const char *s = src; + char *d = buf; + + if (*s == '"') { + ++s; + while (*s && ((d - buf) < bufSize) && *s != '"') *d++ = *s++; + if (*s != '"') return NULL; + ++s; + } + else { + while (*s && ((d - buf) < bufSize) && *s != ',') *d++ = *s++; + } + *d = 0; + + return *s ? s : NULL; +} + +size_t cAuthorization::Write(char* Buffer, size_t BufSize) +{ + static const char *UnAuthorizedMask = "WWW-Authenticate: Digest realm=\"%s\", " + "nonce=\"%s\", opaque=\"%s\", algorithm=\"MD5%s\", qop=\"auth\"\n"; + static const char *AuthorizedMask = "Authorization: Digest username=\"%s\", " + "realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\", opaque=\"%s\", qop=\"auth\", nc=%08X, algorithm=\"MD5%s\", cnonce=\"%s\""; + static const char *AuthenticationMaskDef = "Authentication-Info: qop=auth, nc=%08X, rspauth=\"%s\", cnonce=\"%s\""; + static const char *AuthenticationMaskNew = "Authentication-Info: nextnounce=\"%s\", qop=auth, nc=%08X, rspauth=\"%s\", cnonce=\"%s\""; + size_t n=0; + + if (principal && strcmp(principal->Name(), "unset")) { + static bool timeout = 0; + //TODO: authorization info, should be sent after certain timeout + if (timeout) n = snprintf(Buffer, BufSize, AuthenticationMaskNew, nonce, counter, response, cnonce); + else n = snprintf(Buffer, BufSize, AuthenticationMaskDef, counter, response, cnonce); + } + else if (!principal && tmp && tmp->Name() && tmp->Hash()) { + n = snprintf(Buffer, BufSize, AuthorizedMask, tmp->Name(), tmp->Realm(), nonce, uri, response, opaque, + counter, sessAlgo ? "-sess" : "", cnonce); + } + else { + n = snprintf(Buffer, BufSize, UnAuthorizedMask, Credentials.ApplicationRealm(), nonce, opaque, sessAlgo ? "-sess" : ""); + } + return n; +} + + +// authorization is one line, so conforms to header value. Digest has been broken for readability +// Digest username="ich oder", +// realm="Schnarcher@my.box", +// nonce="59F980BB771C1CC31EE7360C7B06F15D", +// uri="/favicon.ico", +// response="7d060b3de37d132e2f4e4b014b127818", +// opaque="33B9703065AD7E1A1DED1DFE07AA357C", +// qop=auth, +// nc=00000001, +// cnonce="4dd872a6c6debac8" +void cAuthorization::ParseRawBuffer(const char* Raw) +{ + static const char *eyecatch = "Digest"; + + if (strncmp(Raw, eyecatch, strlen(eyecatch))) { +// esyslog("Authentication is not of type Digest! - not supported!"); + + return; + } + char nameBuf[30]; + char scratch[128]; + const char *p = Raw + strlen(eyecatch); + bool done=false; + + if (tmp) { + delete tmp; + tmp = NULL; + } + while (!done) { + p = getAttrName(nameBuf, sizeof(nameBuf), p); + if (*p != '=') { + esyslog("invalid digest format! Expected '=' and found %C (%02X)", *p, *p); + return; + } + p = getValue(scratch, sizeof(scratch), ++p); + SetAttribute(nameBuf, scratch); + + if (!p) break; + if (*p != ',') break; + else ++p; + } +} + +void cAuthorization::SetUser(const char *UserID, const char *Password) +{ + if (principal) { + //TODO: do we really want to support change of user/password on existing principal? + } + else if (tmp) { + tmp->SetName(UserID); + tmp->CreateHash(Password); + CreateClientHash(); + } +} + +void cAuthorization::SetAttribute(char* Name, const char* Value) +{ + char **p = NULL; + +// isyslog("cAuthorization::SetAttribute(\"%s\") => [%s]", Name, Value); + if (!strcasecmp(Name, "username")) { + if (!tmp) tmp = new cPrincipal(Value, "unset"); + else tmp->SetName(Value); + } + else if (!strcasecmp(Name, "realm")) { + if (!tmp) tmp = new cPrincipal("unset", Value); + else tmp->SetRealm(Value); + } + else if (!strcasecmp(Name, "algorithm")) { + if (!strcmp("MD5-sess", Value)) sessAlgo = true; + } + else if (!strcasecmp(Name, "nonce")) p = &nonce; + else if (!strcasecmp(Name, "uri")) p = &uri; + else if (!strcasecmp(Name, "response")) p = &response; + else if (!strcasecmp(Name, "opaque")) p = &opaque; + else if (!strcasecmp(Name, "cnonce")) p = &cnonce; + else if (!strcasecmp(Name, "qop")) { + if (!strncmp(Value, "auth", 4)) p = &qop; + else esyslog("invalid/unsupported auth method! - only \"auth\" supported!"); + } + else if (!strcasecmp(Name, "nc")) { + counter = strtol(Value, NULL, 16); + } + if (p) { + free(*p); + *p = strdup(Value); + } + if (tmp) { + principal = Credentials.FindPrincipal(tmp->Name(), tmp->Realm()); + if (principal) { + delete tmp; + tmp = NULL; + } + } +} + +char * cAuthorization::CalculateA1(const char *Username, const char *Password) +{ + if (Username && Password) SetUser(Username, Password); + char *principalHash = (char *) (principal ? principal->Hash() : tmp->Hash()); + + if (sessAlgo) { + cMD5Calculator hc; + + hc.AddContent(principalHash); + hc.AddContent(":"); + hc.AddContent(nonce); + hc.AddContent(":"); + hc.AddContent(cnonce); + + return hc.Hash(); + } + return strdup(principalHash); +} + +char * cAuthorization::CalculateA2(const char *Uri) +{ + cMD5Calculator hc; + + // don't send method on authorized response + if (!principal || strcmp(principal->Name(), "unset")) hc.AddContent(requestMethod2String(method)); + hc.AddContent(":"); + hc.AddContent(Uri); + + return hc.Hash(); +} + +const char * cAuthorization::CalculateResponse(const char *Uri, const char *Username, const char *Password) +{ + free(response); + char *a1 = CalculateA1(Username, Password); + char *a2 = CalculateA2(Uri ? Uri : uri); + cMD5Calculator hc; + char buf[12]; + + snprintf(buf, sizeof(buf), "%08x", counter); + hc.AddContent(a1); + hc.AddContent(":"); + hc.AddContent(nonce); + if (qop) { + hc.AddContent(":"); + hc.AddContent(buf); + hc.AddContent(":"); + hc.AddContent(cnonce); + hc.AddContent(":"); + hc.AddContent(qop); + } + hc.AddContent(":"); + hc.AddContent(a2); + + response = hc.Hash(); + +// printf("CalculateResponse: Realm-Digest (A1) =>%s<\n", a1); +// printf("CalculateResponse: URL-Digest (A2) =>%s<\n", a2); +// printf("CalculateResponse: Request-Digest =>%s<\n", response); + + free(a1); + free(a2); + + return response; +} + +void cAuthorization::Dump(void) const +{ + printf(">>>---------- Authorization ------------------\n"); + if (principal) principal->Dump(); + else if (tmp) tmp->Dump(); + else printf("principal is NULL\n"); + printf("nonce ...: >%s<\n", nonce); + printf("method ..: >%s<\n", requestMethod2String(method)); + printf("uri .....: >%s<\n", uri); + printf("response : >%s<\n", response); + printf("opaque ..: >%s<\n", opaque); + printf("cnonce ..: >%s<\n", cnonce); + printf("counter .: >%d<\n", counter); + printf("============= Authorization ===============<<<\n"); +} + +// --- Authorizations --------------------------------------------------------- + +static void freeAuthorizationCallback(void *elem) +{ + delete (cAuthorization *)elem; +} + +cAuthorizations::cAuthorizations() + : cManagedVector(freeAuthorizationCallback) +{ +} + +cAuthorizations::~cAuthorizations() +{ +} + +cAuthorization *cAuthorizations::FindAuthorization(const char *SessionID) +{ + cAuthorization *a; + + for (size_t i=0; i < size(); ++i) { + a = (cAuthorization *) (*this)[i]; + if (!strcmp(a->Opaque(), SessionID)) return a; + } + return NULL; +} + +const cAuthorization &cAuthorizations::CreateAuthorization(const cHTTPRequest &originalRequest, const cConnectionPoint &client, unsigned long connectionNumber) +{ + cAuthorization *rv = new cAuthorization(originalRequest, CreateNOnce(client, connectionNumber)); + + push_back(rv); + + return *rv; +} + +char *cAuthorizations::CreateNOnce(const cConnectionPoint &client, unsigned long connectionNumber) +{ + char buf[40]; + cMD5Calculator hc; + + snprintf(buf, sizeof(buf), "%lu:%lu", connectionNumber, random()); + + hc.AddContent(buf); + hc.AddContent(":"); + hc.AddContent(client.HostName()); + + return hc.Hash(); +} + +char *cAuthorizations::CreateSessionID(const cHTTPRequest &OriginalRequest, time_t AuthTime) +{ + char buf[40]; + cMD5Calculator hc; + const char *p0, *p1; + + snprintf(buf, sizeof(buf), "%lu", AuthTime); + + p0 = OriginalRequest.ClientHost(); + p1 = OriginalRequest.UserAgent(); + + hc.AddContent(p0 ? p0 : "localhost"); + hc.AddContent(":"); + hc.AddContent(buf); + hc.AddContent(":"); + hc.AddContent(p1 ? p1 : "unknown"); + + return hc.Hash(); +} + +void cAuthorizations::Del(cAuthorization *Auth2Invalidate) +{ +//TODO: +}
\ No newline at end of file diff --git a/libs/networking/src/ClientSocket.cc b/libs/networking/src/ClientSocket.cc new file mode 100644 index 0000000..db42cf9 --- /dev/null +++ b/libs/networking/src/ClientSocket.cc @@ -0,0 +1,45 @@ +/** + * ======================== legal notice ====================== + * + * File: ClientSocket.cc + * Created: 4. Juli 2012, 07:25 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <ClientSocket.h> + +cClientSocket::cClientSocket(const char *ServerName, int Port) + : cAbstractSocket(ServerName, Port) +{ +} + +cClientSocket::~cClientSocket() +{ +} + +bool cClientSocket::Connect(void) +{ + return cAbstractSocket::Connect(); +} + +void cClientSocket::Close(void) +{ + cAbstractSocket::Close(); +} + diff --git a/libs/networking/src/ConnectionHandler.cc b/libs/networking/src/ConnectionHandler.cc new file mode 100644 index 0000000..c5d5ebf --- /dev/null +++ b/libs/networking/src/ConnectionHandler.cc @@ -0,0 +1,393 @@ +/** + * ======================== legal notice ====================== + * + * File: ConnectionHandler.cc + * Created: 4. Juli 2012, 07:32 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <ConnectionHandler.h> +#include <ServerSocket.h> +#include <HTTPRequest.h> +#include <HTTPFileResponse.h> +#include <HTTPAuthorizationRequest.h> +#include <HTTPRequestHandler.h> +#include <Authorization.h> +#include <Credentials.h> +#include <MD5Calculator.h> +#include <StringBuilder.h> +#include <TimeMs.h> +#include <Logging.h> +#include <util.h> +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <iostream> +#include <tr1/unordered_map> + +static unsigned long connectionCounter = 0; +class cHTTPRequestHandlers { +public: + typedef std::tr1::unordered_map<std::string, cHTTPRequestHandler *>::iterator iterator; + cHTTPRequestHandlers(); + ~cHTTPRequestHandlers(); + + cHTTPRequestHandler *Handler(const char *UrlPrefix); + void SetHandler(const char *UrlPrefix, cHTTPRequestHandler *Handler); + cHTTPRequestHandler *DefaultHandler(void) { return defaultHandler; } + void SetDefaultHandler(cHTTPRequestHandler *Handler) { defaultHandler = Handler; } + + cHTTPRequestHandlers::iterator begin() { return internalMap.begin(); } + cHTTPRequestHandlers::iterator end() { return internalMap.end(); } + +private: + cHTTPRequestHandler *defaultHandler; + std::tr1::unordered_map<std::string, cHTTPRequestHandler *> internalMap; + }; + +cHTTPRequestHandlers::cHTTPRequestHandlers() + : defaultHandler(NULL) +{ +} + +cHTTPRequestHandlers::~cHTTPRequestHandlers() +{ + cHTTPRequestHandlers::iterator it = internalMap.begin(); + + while (it != internalMap.end()) { + delete it->second; + ++it; + } + if (defaultHandler) delete defaultHandler; +} + +cHTTPRequestHandler *cHTTPRequestHandlers::Handler(const char* UrlPrefix) +{ + cHTTPRequestHandlers::iterator it = internalMap.find(UrlPrefix); + + if (it == internalMap.end()) return NULL; + return it->second; +} + +void cHTTPRequestHandlers::SetHandler(const char* UrlPrefix, cHTTPRequestHandler* Handler) +{ + Handler->SetID(UrlPrefix); + internalMap[UrlPrefix] = Handler; +} +static cHTTPRequestHandlers registeredHandlers; + +cConnectionHandler::cConnectionHandler(cConnectionPoint &Client, cServerConfig &Config, bool StayConnected) + : config(Config) + , client(Client) + , connectionNumber(++connectionCounter) + , bufSize(2048) + , scratch(NULL) + , nonce(NULL) + , stayConnected(StayConnected) +{ +} + +cConnectionHandler::~cConnectionHandler() +{ + Cancel(); +} + +void cConnectionHandler::Action() +{ + if (!scratch) scratch = (char *)malloc(bufSize); + if (!scratch) { + esyslog("failed to allocate scratch buffer of size %ld", bufSize); + return; + } + cHTTPRequest *request; + cHTTPResponse *response = NULL; + uint64_t start, end; + size_t nTrans; + + isyslog("ConnectionHandler::Action() - start the loop"); + while (Running()) { + memset(scratch, 0, bufSize); + + // process at least one request + isyslog("read next request from Client"); + nTrans = read(client.Socket(), scratch, bufSize); + if (nTrans < 1) { + esyslog("failed to read client-Request! End of this connection handler ... #%d", errno); + return; + } + start = cTimeMs::Now(); + if (nTrans == bufSize) { + char *p = scratch + nTrans; + + bufSize += 2048; + scratch = (char *) realloc(scratch, bufSize); + nTrans += read(client.Socket(), p, 2048); + + //TODO: should we support multiple buffer resize? + if (nTrans == bufSize) { + esyslog("OUPS - buffer overflow? - Lets stop this connection handler ..."); + return; + } + } + isyslog("#%lu - got client request |>%s<|", connectionNumber, scratch); + + request = new cHTTPRequest(scratch); + if (!request) { + esyslog("ERROR: failed to parse request from client!"); + response = new cHTTPResponse(HTTP_NotAcceptable); + } + else { + isyslog("got request from client (%ld bytes) %s", nTrans, request->Url().Path()); + + if (AuthorizationRequired()) { + if (request->Authorization()) { + char *url = request->Url().ToString(); + + for (EVER) { + //TODO: 1, check uri from request against uri from auth + if (strcmp(request->Authorization()->Uri(), url)) { + esyslog("ATTENTION - security attack! URI mismatch between request and authorization header!"); + response = new cHTTPResponse(HTTP_BadRequest); + break; + } + + //TODO: 2. search user/principal + cAuthorization *auth = Authorizations().FindAuthorization(request->Authorization()->Opaque()); + + if (!auth) { + response = new cHTTPAuthorizationRequest(Authorizations().CreateAuthorization(*request, client, connectionNumber)); + esyslog("Huh? - didn't find a matching authorization, but client sent authorization header. Something went wrong!"); + break; + } + + //TODO: 3. check auth->principal->hash against hash from found principal + if (IsAuthorizationValid(auth, *request)) + response = ProcessRequest(*request); + if (!response) { + //TODO: 406 or should we create a new authorization request? + response = new cHTTPResponse(HTTP_NotAcceptable); + } + break; + } + free(url); + } + else { + //TODO: create authorization request + response = new cHTTPAuthorizationRequest(Authorizations().CreateAuthorization(*request, client, connectionNumber)); + } + } + else response = ProcessRequest(*request); + } + TransferResponse(response); + delete response; + delete request; + response = NULL; + request = NULL; + end = cTimeMs::Now(); + isyslog("processing of request took %ld ms.", (end - start)); + + isyslog("check IO status ..."); + if (!client.IOWait(500)) { + if (!StayConnected()) { + isyslog(" >>> connection timed out without any data <<<"); + break; // leave temporary connections after timeout + } + } + } + Cancel(); +} + +void cConnectionHandler::Cancel(int WaitSeconds) +{ + dsyslog("Ok, lets close the client socket ..."); + client.Close(); + FREE(scratch); + FREE(nonce); +} + +bool cConnectionHandler::IsAuthorizationValid(cAuthorization *ServerAuth, const cHTTPRequest &request) +{ + // Auth is the authorization based on opaque value from request->auth (session-ID) + // check other values from auth/request too + const cAuthorization *ClientAuth = request.Authorization(); + const cPrincipal *principal = ServerAuth->Principal(); + + if (!principal || !strcmp(ServerAuth->UserID(), "unset")) + principal = Credentials.FindPrincipal(ClientAuth->UserID(), ClientAuth->Realm()); + + for (EVER) { + if (!principal) { + esyslog("username or realm is unknown"); + break; + } + if (strcmp(ClientAuth->UserID(), principal->Name()) || strcmp(ClientAuth->Realm(), principal->Realm())) { + esyslog("username or realm did not match authenticated session"); + break; + } + if (strcmp(principal->Hash(), ClientAuth->UserCredential())) { + esyslog("password given was invalid"); + break; + } + cAuthorization *authCheck = new cAuthorization(principal, request.Method(), *ClientAuth); + const char *authHash = authCheck->CalculateResponse(); + + if (strcmp(authHash, ClientAuth->Response())) { + delete authCheck; + break; + } + + if (strcmp(ServerAuth->UserID(), principal->Name())) { + // validation passed, so remember authorized user + ServerAuth->SetPrincipal(principal); + } + delete authCheck; + + return true; + } + // validation of authorization failed, so remove any existing authorization from this session + Authorizations().Del(ServerAuth); + + return false; +} + +cHTTPResponse *cConnectionHandler::ProcessRequest(cHTTPRequest &Request) +{ + cHTTPResponse *res = NULL; + + isyslog("ConnectionHandler::ProcessRequest: %s", Request.Url().Path()); + if (!strcmp(Request.Url().Path(), "/stop")) { + ServerSocket().SetActive(false); + res = new cHTTPResponse(HTTP_Gone); + } + else if (!strcmp(Request.Url().Path(), "/favicon.ico")) { + res = new cHTTPFileResponse(config.AppIconPath()); + } + else if (!strcmp(Request.Url().Path(), "/help")) { + cHTTPResponse *ir = new cHTTPResponse(); + + isyslog("start assembling usage message ..."); + Usage(ir->StringBuilder()); + + ir->StringBuilder().Append("<hr>").Append(ir->ServerID()).Append(" ").Append(config.DocumentRoot()); + isyslog("assembling of usage message done - let's send it to client ..."); + ir->SetContentType("text/html"); + ir->SetContentSize(ir->StringBuilder().Size()); + res = ir; + } + else { + cHTTPRequestHandler *rh = registeredHandlers.Handler(Request.Url().Path()); + + if (rh) res = rh->ProcessRequest(Request); + if (!rh || !res) { + rh = registeredHandlers.DefaultHandler(); + + if (rh) res = rh->ProcessRequest(Request); + } + } + if (!res) res = new cHTTPResponse(HTTP_NotFound); + + return res; +} + +void cConnectionHandler::Usage(cStringBuilder& sb) +{ + cHTTPRequestHandlers::iterator it = registeredHandlers.begin(); + + isyslog("start of cConnectionHandler::Usage() ..."); + sb.Append("<h2>Media server</h2><p>serves media files to remote/client media-players. Those "); + sb.Append("media-player should support the http-protocol. Opposed to well known http-servers, this "); + sb.Append("server handles multifile media transparently for the client.</p>"); + sb.Append("<h3>supported requests:</h3>"); + sb.Append("<dl>"); + + while (it != registeredHandlers.end()) { + sb.Append("<dt><br/><em>"); + sb.Append(it->first.c_str()); + sb.Append("</em></dt><dd>"); + it->second->Usage(sb); + sb.Append("</dd>"); + ++it; + } + if (registeredHandlers.DefaultHandler()) { + sb.Append("<dt><br/><em>"); + sb.Append("default"); + sb.Append("</em></dt><dd>"); + registeredHandlers.DefaultHandler()->Usage(sb); + sb.Append("</dd>"); + sb.Append("</dl>"); + } + isyslog("end of cConnectionHandler::Usage() ..."); +} + +void cConnectionHandler::TransferResponse(cHTTPResponse *Response) +{ + if (!Response) { + esyslog("OUPS - should not happen!!! - Response was empty!"); + close(client.Socket()); + + return; + } +//#ifdef DEBUG +// static int responseCounter = 0; +// char filename[64] = {0}; +// sprintf(filename, "/tmp/rednose%03d", ++responseCounter); +//#endif + + memset(scratch, 0, bufSize); + +//#ifdef DEBUG +// int fdClient = open(filename, O_WRONLY | O_CREAT); +//#else + int fdClient = client.Socket(); +//#endif + isyslog("gonna sent message to client (Socket #%d)", fdClient); + + int nRaw = Response->WritePrefix(scratch, bufSize); + int nTrans = send(fdClient, scratch, nRaw, MSG_NOSIGNAL); + size_t total = 0; + + if (nTrans != nRaw) esyslog("ERROR: failed to transmit response header! (%d <> %d)", nRaw, nTrans); + while ((nRaw = Response->ReadContentChunk(scratch, bufSize)) > 0) { + int nTrans = send(fdClient, scratch, nRaw, MSG_NOSIGNAL); + + if (nTrans < 1) { + esyslog("failed to transmit chunk. Error #%d", errno); + break; + } + total += nTrans; + if (nTrans == nRaw) isyslog("successfully written message chunk of %d bytes", nTrans); + else esyslog("failed to transmit response chunk (%d <> %d)", nRaw, nTrans); + } + if (total != Response->ContentSize()) + esyslog("failed to transfer response - should be %ld, was %ld", Response->ContentSize(), total); +//#ifdef DEBUG +// close(fdClient); +//#endif +} + +void cConnectionHandler::RegisterDefaultHandler(cHTTPRequestHandler *DefaultHandler) +{ + registeredHandlers.SetDefaultHandler(DefaultHandler); +} + +void cConnectionHandler::RegisterRequestHandler(const char *UrlPrefix, cHTTPRequestHandler *RequestHandler) +{ + registeredHandlers.SetHandler(UrlPrefix, RequestHandler); +} diff --git a/libs/networking/src/ConnectionPoint.cc b/libs/networking/src/ConnectionPoint.cc new file mode 100644 index 0000000..4700652 --- /dev/null +++ b/libs/networking/src/ConnectionPoint.cc @@ -0,0 +1,89 @@ +/** + * ======================== legal notice ====================== + * + * File: ConnectionPoint.cc + * Created: 4. Juli 2012, 06:29 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <ConnectionPoint.h> +#include <util.h> +#include <poll.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> + +cConnectionPoint::cConnectionPoint(const char *NameOrIP, int Port, const char *RealName) + : nameOrIP(strdup(NameOrIP)) + , realName(RealName ? strdup(RealName): NULL) + , combined(NULL) + , port(Port) + , sock(-1) +{ +} + +cConnectionPoint::~cConnectionPoint() +{ + Close(); +} + +void cConnectionPoint::Close() +{ + if (sock > 0) { + close(sock); + sock = -1; + } + FREE(nameOrIP); + FREE(realName); + FREE(combined); +} + +void cConnectionPoint::SetRealName(const char *Name) +{ + FREE(realName); + realName = Name ? strdup(Name) : NULL; +} + +int cConnectionPoint::IOWait(long MilliSeconds) +{ + struct pollfd fds; + + fds.fd = sock; + fds.events = POLLIN | POLLPRI; + + int rv = poll(&fds, 1, MilliSeconds); + + if (rv > 0) return fds.revents; // so app can ask for priority events + return rv; +} + +const char *cConnectionPoint::AssembleCombined() const +{ + FREE(combined); + size_t len = strlen(nameOrIP) + 16; + + if (realName) len += strlen(realName); + char *p = (char *)malloc(len); + + if (realName) snprintf(p, len, "%s:%d (%s)", nameOrIP, port, realName); + else snprintf(p, len, "%s:%d", nameOrIP, port); + if (p) ((cConnectionPoint *)this)->combined = p; + + return combined; +} diff --git a/libs/networking/src/Credentials.cc b/libs/networking/src/Credentials.cc new file mode 100644 index 0000000..db1e219 --- /dev/null +++ b/libs/networking/src/Credentials.cc @@ -0,0 +1,171 @@ +/** + * ======================== legal notice ====================== + * + * File: Credentials.cc + * Created: 3. Juli 2012, 14:37 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <Credentials.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +cCredentials Credentials; +static const char *appRealm = NULL; + +cCredentials::cCredentials() +{ +} + +cCredentials::~cCredentials() +{ + Clear(); +} + +void cCredentials::Clear() +{ + iterator it = internalMap.begin(); + + while (it != internalMap.end()) { + delete it->second; + ++it; + } +} + +const char *cCredentials::ApplicationRealm() const +{ + return appRealm; +} + +const cPrincipal *cCredentials::FindPrincipal(const char* Name, const char* Realm) +{ + std::string tmp = Name; + cPrincipal *rv = internalMap[tmp]; + + if (!strcmp(rv->Name(), Name) && !strcmp(rv->Realm(), Realm)) return rv; + return NULL; +} + +void cCredentials::SetApplicationRealm(const char* ApplicationRealm) +{ + appRealm = ApplicationRealm; +} + +void cCredentials::Put(const char* Key, cPrincipal* p) +{ + internalMap[Key] = p; +} + +cPrincipal *cCredentials::Get(const char* Key) +{ + iterator it = internalMap.find(Key); + + if (it != internalMap.end()) return it->second; + return NULL; +} + +int cCredentials::Load(const char *FileName) +{ + char buf[256]; + FILE *fp = fopen(FileName, "r"); + cPrincipal *principal = NULL; + char *chunk = buf; + int principalsProcessed = 0; + int bytesRead = 0; + + if (!fp) { + //TODO: verbose message? + return 0; + } + while ((bytesRead = fread(chunk, sizeof(char), sizeof(buf) - (chunk - buf), fp)) > 0) { + char *endOfLine = index(buf, '\n'); + + while (chunk && endOfLine) { + principal = parsePrincipal(chunk, endOfLine - chunk); + if (!principal) break; + std::string userid = principal->Name(); + + internalMap[userid] = principal; + ++principalsProcessed; + chunk = endOfLine < (buf + sizeof(buf)) ? endOfLine + 1 : NULL; + endOfLine = index(chunk, '\n'); + } + // shift rest of buffer down and read a smaller chunk + if (chunk && !endOfLine) { + int rest = sizeof(buf) - (chunk - buf); + + memmove(buf, chunk, rest); + chunk = buf + rest; + } + } + fclose(fp); + + return principalsProcessed; +} + +cPrincipal *cCredentials::parsePrincipal(char* buf, size_t bufSize) +///< format is: name:hash:age:extendedInfo +{ + if (!buf || !*buf || bufSize < 30) return NULL; + cPrincipal *rv = NULL; + char *hash = index(buf, ':') + 1; + char *age = index(hash, ':') + 1; + char *xi = index(age, ':') + 1; + + if (hash == (char *)1 || !*hash) return NULL; + if (age == (char *)1 || !*age) return NULL; + if (xi == (char *)1 || !*xi) return NULL; + + *(hash - 1) = 0; + *(age - 1) = 0; + *(xi - 1) = 0; + *(buf + bufSize - 1) = 0; + + rv = new cPrincipal(buf, ApplicationRealm()); + if (rv) { + rv->SetHash(hash); + rv->SetAge(atoi(age)); + rv->SetExtendedInfo(xi); + } + return rv; +} + +int cCredentials::Store(const char* FileName) +{ + FILE *fp = fopen(FileName, "w"); + cPrincipal *p; + int principalsProcessed = 0; + + if (!fp) { + //TODO: verbose message? + return 0; + } + cCredentials::const_iterator principals = begin(); + + while (principals != end()) { + p = principals->second; + fprintf(fp, "%s:%s:%d:%s\n", p->Name(), p->Hash(), p->Age(), p->ExtendedInfo() ? p->ExtendedInfo() : " "); + ++principalsProcessed; + ++principals; + } + fclose(fp); + + return principalsProcessed; +}
\ No newline at end of file diff --git a/libs/networking/src/HTTPAuthorizationRequest.cc b/libs/networking/src/HTTPAuthorizationRequest.cc new file mode 100644 index 0000000..5c558f8 --- /dev/null +++ b/libs/networking/src/HTTPAuthorizationRequest.cc @@ -0,0 +1,47 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPAuthorizationRequest.cc + * Created: 4. Juli 2012, 07:41 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPAuthorizationRequest.h> +#include <Authorization.h> +#include <HTTPRequest.h> +#include <stddef.h> + +cHTTPAuthorizationRequest::cHTTPAuthorizationRequest(const cHTTPRequest &OriginalRequest, char *NOnceFromHeap) + : cHTTPResponse(HTTP_UnAuthorized) +{ + SetHeader("Connection", "Close"); + SetAuthorization(new cAuthorization(OriginalRequest, NOnceFromHeap ? strdup(NOnceFromHeap) : NULL)); +} + +cHTTPAuthorizationRequest::cHTTPAuthorizationRequest(const cAuthorization &Authorization) + : cHTTPResponse(HTTP_UnAuthorized) +{ + SetHeader("Connection", "Close"); + SetAuthorization(new cAuthorization(Authorization)); +} + +cHTTPAuthorizationRequest::~cHTTPAuthorizationRequest() +{ +} + diff --git a/libs/networking/src/HTTPFileResponse.cc b/libs/networking/src/HTTPFileResponse.cc new file mode 100644 index 0000000..d79b085 --- /dev/null +++ b/libs/networking/src/HTTPFileResponse.cc @@ -0,0 +1,102 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPFileResponse.cc + * Created: 4. Juli 2012, 07:50 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPFileResponse.h> +#include <Logging.h> +#include <util.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> + +cHTTPFileResponse::cHTTPFileResponse(const char *RealPath) + : cHTTPResponse(HTTP_OK) + , realPath(RealPath) + , fd(0) +{ + DetermineTypeAndSize(realPath); +} + +cHTTPFileResponse::cHTTPFileResponse() + : cHTTPResponse(HTTP_OK) + , realPath(NULL) + , fd(0) +{ +} + +cHTTPFileResponse::~cHTTPFileResponse() +{ +} + +void cHTTPFileResponse::DetermineTypeAndSize(const char* Path) +{ + struct stat st; + const char *xt; + + if (!Path) return; + if (stat(Path, &st) < 0) { + esyslog("invalid path given - %d", errno); + return; + } + SetContentSize(st.st_size); + xt = strrchr(Path, '.'); + if (!xt) SetContentType(MT_Unknown); + ++xt; + + // File response serves only simple files, like tiny webservers + if (!strcasecmp("html", xt)) SetContentType(MT_Html); + else if (!strcasecmp("css", xt)) SetContentType(MT_CSS); + else if (!strcasecmp("js", xt)) SetContentType(MT_JavaScript); + else if (!strcasecmp("ico", xt)) SetContentType(MT_Ico); + else if (!strcasecmp("gif", xt)) SetContentType(MT_Gif); + else if (!strcasecmp("png", xt)) SetContentType(MT_Png); + else if (!strcasecmp("jpg", xt)) SetContentType(MT_Jpg); + else if (!strcasecmp("jpeg", xt)) SetContentType(MT_Jpg); + else if (!strcasecmp("dtd", xt)) SetContentType(MT_XmlDtd); + else if (!strcasecmp("xml", xt)) SetContentType(MT_Xml); +} + +size_t cHTTPFileResponse::ReadContentChunk(char* Buf, size_t bufSize) +{ + long rv = 0; + + if (fd < 1) { + fd = open(RealPath(), O_RDONLY | O_LARGEFILE); + if (fd < 1) { + esyslog("could not open requested path %s - Error #%d", RealPath(), errno); + return 0; + } + } + isyslog("have filehandle #%d (%s)", fd, RealPath()); + if ((rv = read(fd, Buf, bufSize)) < 0) + esyslog("ERROR: failed to read from file %s #%d", RealPath(), errno); + else + isyslog("read %u bytes from file", rv); + if (rv < (long) bufSize) { // most probabely end of file + close(fd); + } + return rv; +} diff --git a/libs/networking/src/HTTPMessage.cc b/libs/networking/src/HTTPMessage.cc new file mode 100644 index 0000000..9e1b5ba --- /dev/null +++ b/libs/networking/src/HTTPMessage.cc @@ -0,0 +1,165 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPMessage.cc + * Created: 3. Juli 2012, 17:40 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPMessage.h> +#include <Authorization.h> +#include <stdio.h> +#include <stddef.h> +#include <util.h> + +static void freeHeaderCallback(void *elem) +{ + free(elem); +} + +cHTTPMessage::cHTTPMessage(HTTPProtocol Proto) + : protocol(Proto) + , timeStamp(0) + , header(freeHeaderCallback) + , auth(NULL) + , contentSize(0) + , contentType(NULL) +{ +} + +cHTTPMessage::~cHTTPMessage() +{ + if (auth) delete auth; + FREE(contentType); +} + +char *cHTTPMessage::FormatTime(time_t timeStamp) +{ + struct tm *t = gmtime(&timeStamp); + char buf[128]; + + strftime(buf, sizeof(buf), "%a, %d %b %Y %H:%M:%S GMT", t); + + return strdup(buf); +} + +void cHTTPMessage::SetHeader(const char *Name, const char *Value) +{ + header.put(Name, Value ? strdup(Value) : NULL); +} + +const char *cHTTPMessage::GetHeader(const char* Name) const +{ + return (const char *) header.get(Name); +} + +size_t cHTTPMessage::WritePrefix(char *Buffer, size_t BufSize) +///< writes message prefix to existing buffer. Prefix is the message without +///< the content body, so internal and external content will be processed +///< separately. +///< IMPORTANT: content size and content type has to be set before this call! +///< or this information needs to be added by custom call. +{ + cManagedMap::const_iterator it = Headers().begin(); + size_t n = WriteFirstLine(Buffer, BufSize); + + strcpy(Buffer + n, "Date: "); + n += 6; + n += WriteTime(Buffer + n, BufSize - n); + while (it != Headers().end()) { + n += snprintf(Buffer + n, BufSize - n, "%s: %s\r\n", it->first.c_str(), (const char *) it->second); + ++it; + } + if (auth) n += auth->Write(Buffer + n, BufSize - n); + if (ContentSize() > 0) { + n += snprintf(Buffer + n, BufSize - n, "Content-Type: %s\r\n", ContentType()); + n += snprintf(Buffer + n, BufSize - n, "Content-Length: %ld\r\n", ContentSize()); + if (n < BufSize - 3) { + Buffer[n++] = '\n'; // this is the separator between header and content! + Buffer[n] = 0; + } + } + return n; +} + +int cHTTPMessage::WriteTime(char *Buffer, size_t BufSize) +{ + if (!timeStamp) timeStamp = time(NULL); + struct tm *t = gmtime(&timeStamp); + + return strftime(Buffer, BufSize, "%a, %d %b %Y %H:%M:%S GMT\r\n", t); +} + +void cHTTPMessage::Reset() +{ + header.clear(); + contentSize = 0; +} + +size_t cHTTPMessage::ContentSize() const +{ + return contentSize; +} + +void cHTTPMessage::SetContentType(const char* ContentType) +{ + FREE(contentType); + contentType = ContentType ? strdup(ContentType) : NULL; +} + +void cHTTPMessage::SetAuthorization(cAuthorization* Authorization) +{ + if (auth) { + delete auth; + auth = NULL; + } + auth = Authorization; +} + +const char *cHTTPMessage::ProtocolString(void) { + switch (protocol) { + case HTTP_1_0: return "HTTP/1.0"; + case HTTP_1_1: return "HTTP/1.1"; + default: return "Unknown/Unsupported"; + } +} + +void cHTTPMessage::Dump(void ) +{ + cManagedMap::const_iterator it = Headers().begin(); + char buf[1024]; + + WriteFirstLine(buf, sizeof(buf)); + printf("=========== Dump HTTP message ==============\n"); + printf("Protocol: %s\n", ProtocolString()); + printf("first line: %s\n", buf); + printf("header entries:\n"); + while (it != Headers().end()) { + printf("\t[%s] ==> >|%s|<\n", it->first.c_str(), (const char *) it->second); + ++it; + } + if (auth) auth->Dump(); + if (ContentSize()) { + printf("---------- content (%ld Bytes of type %s) -------------\n" + , ContentSize(), ContentType()); + } + else printf(">>> NO Content!\n"); + printf("========== End Dump HTTP message ===========\n"); +} + diff --git a/libs/networking/src/HTTPParser.cc b/libs/networking/src/HTTPParser.cc new file mode 100644 index 0000000..2fc1dad --- /dev/null +++ b/libs/networking/src/HTTPParser.cc @@ -0,0 +1,42 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPParser.cc + * Created: 10. Juli 2012, 08:37 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPParser.h> +#include <HTTPRequest.h> +#include <HTTPResponse.h> +#include <string.h> + +cHTTPParser::cHTTPParser() +{ +} + +cHTTPParser::~cHTTPParser() +{ +} + +cHTTPMessage *cHTTPParser::ParseMessage(const char* MessageBuf) +{ + if (!strncmp("HTTP", MessageBuf, 4)) return new cHTTPResponse(MessageBuf); + return new cHTTPRequest(MessageBuf); +} diff --git a/libs/networking/src/HTTPRequest.cc b/libs/networking/src/HTTPRequest.cc new file mode 100644 index 0000000..c17b29c --- /dev/null +++ b/libs/networking/src/HTTPRequest.cc @@ -0,0 +1,171 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPRequest.cc + * Created: 3. Juli 2012, 17:54 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPRequest.h> +#include <HTTPResponse.h> +#include <Authorization.h> +#include <Principal.h> +#include <Logging.h> +#include <util.h> +#include <stdio.h> + + +cHTTPRequest::cHTTPRequest(const char *MessageBuf) + : method(INVALID) + , url(NULL) +{ + ParseMessage(MessageBuf); +} + +cHTTPRequest::cHTTPRequest(cHTTPRequest::HTTPRequestMethod Method, const char* Url) + : method(Method) + , url(Url) +{ +} + +cHTTPRequest::cHTTPRequest(const cHTTPResponse &res, const char *Url) + : method(cHTTPRequest::GET) + , url(Url) +{ + SetAuthorization(new cAuthorization(*res.Authorization())); + Authorization()->SetUri(Url); +} + + +cHTTPRequest::~cHTTPRequest() +{ +} + +const char *requestMethod2String(cHTTPRequest::HTTPRequestMethod Method) +{ + switch (Method) { + case cHTTPRequest::GET: return "GET"; + case cHTTPRequest::POST: return "POST"; + default: return "unknown/unsupported"; + } +} + +void cHTTPRequest::SetURL(const char *Url) +{ + url.ParseURL(Url); +} + +const char *cHTTPRequest::ClientHost(void ) const +{ + return (const char *) Headers().get("Host"); +} + +const char *cHTTPRequest::UserAgent() const +{ + return (const char *) Headers().get("User-Agent"); +} + +void cHTTPRequest::SetUser(const char *UserID, const char *Password) +{ + char *uri = Url().ToString(); + this->Authorization()->CalculateResponse(uri, UserID, Password); + free(uri); +} + +static const char *fetchLine(char *Buf, int BufSize, const char *Source) +{ + const char *end = strchr(Source, '\r'); + int len = 0; + + if (!end) end = strchr(Source, '\n'); + if (!end) end = Source + strlen(Source); + len = end - Source; + if (len > BufSize) len = BufSize - 1; + + strncpy(Buf, Source, len); + Buf[len] = 0; + end = Source + len; + + return end; +} + +void cHTTPRequest::ParseMessage(const char *RequestBuf) +{ + char scratch[512]; + const char *start = RequestBuf, *end = strchr(start, ' '); + const char *name; + char *value; + + if (strncasecmp("GET", start, end - start)) SetMethod(GET); + else if (strncasecmp("POST", start, end - start)) SetMethod(POST); + start = end; + while (*start == ' ') ++start; + end = strchr(start, ' '); +// printf("request-URI %*.*s\n", (int)(end - start), (int)(end - start), start); + if ((end - start) >= (int)sizeof(scratch)) { + esyslog("URI exhausted buffer - abort request!"); + return; + } + else { + strncpy(scratch, start, end - start); + scratch[end - start] = 0; + SetURL(scratch); + } + start = end; + while (*start == ' ') ++start; + end = strchr(start, '\r'); + if (!end) end = strchr(start, '\n'); +// printf("http-protocol %*.*s\n", (int)(end - start), (int)(end - start), start); + if (!strncmp("HTTP/1.1", start, end - start)) SetProtocol(HTTP_1_1); + else SetProtocol(HTTP_1_0); + + for (start = end; start && *start; start = end) { + if (*start == '\r') ++start; + if (*start == '\n') ++start; + if (!*start) break; + end = fetchLine(scratch, sizeof(scratch), start); +// printf("a line from request (%03d) [%s]\n", strlen(scratch), scratch); + + name = scratch; + value = strchr((char *)name, ':'); + if (value) { + if (value) *value++ = 0; + if (*value == ' ') *value++ = 0; + + SetHeader(name, value); + } + else { +// printf("possibly end of header ...\n"); + continue; + } +// printf("\nresult - name [%s] => |>%s<|\n", name, value); + } +} + +size_t cHTTPRequest::WriteFirstLine(char* Buffer, size_t BufSize) +{ + size_t n = snprintf(Buffer, BufSize, "%s ", requestMethod2String(Method())); + int tmp = url.WriteBuf(Buffer + n, BufSize - n); + + if (tmp > 0) n += tmp; + n += snprintf(Buffer + n, BufSize - n, " %s\n", ProtocolString()); + + return n; +} + diff --git a/libs/networking/src/HTTPRequestHandler.cc b/libs/networking/src/HTTPRequestHandler.cc new file mode 100644 index 0000000..60ce8d9 --- /dev/null +++ b/libs/networking/src/HTTPRequestHandler.cc @@ -0,0 +1,43 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPRequestHandler.cc + * Created: 4. Juli 2012, 15:12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPRequestHandler.h> +#include <string.h> +#include <util.h> + +cHTTPRequestHandler::cHTTPRequestHandler() + : prefix(NULL) +{ +} + +cHTTPRequestHandler::~cHTTPRequestHandler() +{ + FREE(prefix); +} + +void cHTTPRequestHandler::SetID(const char* UrlPrefix) +{ + FREE(prefix); + prefix = UrlPrefix ? strdup(UrlPrefix) : NULL; +}
\ No newline at end of file diff --git a/libs/networking/src/HTTPResponse.cc b/libs/networking/src/HTTPResponse.cc new file mode 100644 index 0000000..2f0eeef --- /dev/null +++ b/libs/networking/src/HTTPResponse.cc @@ -0,0 +1,183 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPResponse.cc + * Created: 4. Juli 2012, 06:03 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPResponse.h> +#include <Authorization.h> +#include <stddef.h> +#include <stdio.h> +#include <util.h> + +static const char *serverID = NULL; +cHTTPResponse::cHTTPResponse(HTTPStatusCode Status) + : status(Status) + , content(512) +{ + SetHeader("Server", serverID); + if (!(Status <= HTTP_OK /* || Status == HTTP_NoContent */ || Status == 304)) + SetDefaultStatusBody(Status); +} + +cHTTPResponse::cHTTPResponse(const char *Buffer) +{ + ParseMessage(Buffer); + if (Authorization()) Authorization()->SetServerID(ServerID()); +} + +cHTTPResponse::~cHTTPResponse() +{ +} + +size_t cHTTPResponse::ContentSize() const +{ + if (content.Size()) return content.Size(); + return cHTTPMessage::ContentSize(); +} + +const char * cHTTPResponse::ServerID(void) +{ + return serverID; +} + +void cHTTPResponse::SetServerID(const char* ServerID) +{ + serverID = ServerID; +} + +void cHTTPResponse::SetDefaultStatusBody(HTTPStatusCode Status) +{ + SetContentType(MT_Html); + content.Append("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" " +"\"http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd\">\n" +"<HTML>\n" +" <HEAD>\n" +" <TITLE>Error "); + content.Append(Status).Append("</TITLE>\n" +" <META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=ISO-8859-1\">\n" +" </HEAD>\n" +" <BODY><H1>"); + content.Append(Status).Append(" ").Append(httpStatus2Text(Status)).Append(".</H1></BODY>\n" +"</HTML>\n"); +} + +size_t cHTTPResponse::ReadContentChunk(char* Buf, size_t bufSize) +{ + return content.Copy(Buf, bufSize); +} + +size_t cHTTPResponse::WriteFirstLine(char* Buffer, size_t BufSize) +{ + return snprintf(Buffer, BufSize, "%s %d %s\n", ProtocolString(), status, httpStatus2Text(status)); +} + +//static const char *SampleRawResponse = +//HTTP/1.1 401 Unauthorized +//Date: Tue, 29 May 2012 03:54:02 GMT +//Server: (null) +//Connection: Close +//WWW-Authenticate: Digest realm="validUsers@MyTestApp", nonce="dbe67572c707d25689a394ef7a9a9e8c", opaque="94c70a11bef0589719f190baf192bbcd", qop="auth" +//Content-Type: text/html +//Content-Length: 301 + +//<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd"> +//<HTML> +// <HEAD> +// <TITLE>Error</TITLE> +// <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1"> +// </HEAD> +// <BODY><H1>401 Unauthorized.</H1></BODY> +//</HTML> +// +void cHTTPResponse::ParseMessage(const char *RawMessage) +{ + char scratch[512]; + const char *p = RawMessage; + char *tmp; + ParseState state = ExpectProtocol; + ParseResult status = Continue; + + Reset(); + while (status == Continue) { + memset(scratch, 0, sizeof(scratch)); + switch (state) { + case ExpectStatus: + p = getWord(scratch, sizeof(scratch), p); + this->status = strtoHTTPStatus(scratch); + p = restOfLine(scratch, sizeof(scratch), p); // just read the rest of the line + state = ExpectHeader; + break; + + case ExpectProtocol: + p = getWord(scratch, sizeof(scratch), p); + if (!strcmp(scratch, "HTTP/1.0")) { + SetProtocol(HTTP_1_0); + state = ExpectStatus; + } + else if (!strcmp(scratch, "HTTP/1.1")) { + SetProtocol(HTTP_1_1); + state = ExpectStatus; + } + else status = UnsupportedProtocol; + break; + + case ExpectContent: + printf("should read %ld bytes from %10.10s\n", ContentSize(), p); + status = Done; + break; + + case ExpectHeader: + p = getWord(scratch, sizeof(scratch), p); + if (!strncmp(p, "\n\n", 2)) { + p += 2; + state = ExpectContent; + break; + } + if (!strncmp(p, "\r\n\r\n", 4)) { + p += 4; + state = ExpectContent; + break; + } + tmp = scratch + strlen(scratch); + if (*(tmp -1) == ':') { + *(tmp -1) = 0; + tmp = strdup(scratch); + p = restOfLine(scratch, sizeof(scratch), p); + if (!strcasecmp(tmp, "WWW-Authenticate") || !strcasecmp(tmp, "Authorization-Info")) + SetAuthorization(new cAuthorization(cHTTPRequest::GET, scratch)); + else if (!strcasecmp(tmp, "content-type")) + SetContentType(scratch); + else if (!strcasecmp(tmp, "content-length")) + SetContentSize(atol(scratch)); + else SetHeader(tmp, scratch); + FREE(tmp); + } + else { + status = InvalidName; + } + break; + + default: break; + } // end switch + } // end while (status == OK) +} + diff --git a/libs/networking/src/HTTPServer.cc b/libs/networking/src/HTTPServer.cc new file mode 100644 index 0000000..f435e2f --- /dev/null +++ b/libs/networking/src/HTTPServer.cc @@ -0,0 +1,156 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPServer.cc + * Created: 4. Juli 2012, 12:16 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPServer.h> +#include <HTTPResponse.h> +#include <ConnectionHandler.h> +#include <CondWait.h> +#include <Mutex.h> +#include <Logging.h> +#include <util.h> +#include <stdio.h> + +static volatile bool running = true; +cHTTPServer::cHTTPServer(cServerConfig &Config) + : config(Config) +#ifdef LIVE_CLEANUP + , cleaner(NULL) +#endif +{ + threads = new std::vector<cThread *>(); +#ifdef LIVE_CLEANUP + cleaner = new cThread(cleanerThread, NULL, "cleanup thread stubs"); +#endif +} + +cHTTPServer::~cHTTPServer() +{ +#ifdef LIVE_CLEANUP + cleaner->Cancel(0); + delete cleaner; +#else + Cleanup(); +#endif + delete threads; +} + +void cHTTPServer::Action() +{ +#ifdef LIVE_CLEANUP + if (cleaner) { + fprintf(stderr, "check size of thread pool ...\n"); + if (!threads->empty()) fprintf(stderr, "thread pool has size of %lu\n", threads->size()); + fprintf(stderr, "start cleaner thread\n"); + cleaner->Start(); + } +#endif + fprintf(stderr, "startup server now\n"); + while (Running()) { + cConnectionPoint *cp = ServerSocket().Accept(); + + if (cp) { + // this has to come after accept, as the hostnames can not be determined before an established connection. + if (!cHTTPResponse::ServerID()) { + char *id; + + asprintf(&id, "HTTPServer %s:%d", ServerSocket().ThisSide()->RealName(), ServerSocket().Port()); + cHTTPResponse::SetServerID(id); + } + cConnectionHandler *ch = new cConnectionHandler(*cp, config); + + ch->Start(); + +#ifdef LIVE_CLEANUP + cMutexLock poolSync(&poolMutex); +#endif + threads->push_back(ch); + } + } +} + +bool cHTTPServer::Running() +{ + return ServerSocket().Active(); +} + +#ifdef LIVE_CLEANUP +int cHTTPServer::cleanerThread(void *opaque, cThread *ThreadContext) +{ + cHTTPServer *server = (cHTTPServer *)opaque; + + server->Cleanup(ThreadContext); + return 0; +} + +void cHTTPServer::Cleanup(cThread *ThreadContext) +{ + if (!ThreadContext) return; + cThread *p; + + fprintf(stderr, "cleanup-Thread - gonna start loop ...\n"); + while (ThreadContext->Running()) { + fprintf(stderr, "check list of possible threads ...\n"); + if (!threads->empty()) { + fprintf(stderr, "thread pool is not empty ...\n"); + for (size_t i=0; i < threads->size(); ++i) { + fprintf(stderr, "ok, got first entry to check ...\n"); + p = (*threads)[i]; + if (p->Active()) continue; + + fprintf(stderr, "thread %lu looks dead ...\n", i); + isyslog("thread %lu is not active, so just clean it up", i); + p->Cancel(); + delete p; + cMutexLock poolSync(&poolMutex); + threads->erase(threads->begin() + i); + break; + } + } + cCondWait::SleepMs(200); + } + ThreadContext->Cancel(); +} +#else +void cHTTPServer::Cleanup() +{ + cThread *t; + + for (size_t i=0; i < threads->size(); ++i) { + t = (*threads)[i]; + t->Cancel(); + delete t; + } +} +#endif + +bool cHTTPServer::Start() +{ + Action(); + return true; +} + +void cHTTPServer::Stop() +{ + ServerSocket().SetActive(false); +}
\ No newline at end of file diff --git a/libs/networking/src/HTTPStatus.cc b/libs/networking/src/HTTPStatus.cc new file mode 100644 index 0000000..74623ed --- /dev/null +++ b/libs/networking/src/HTTPStatus.cc @@ -0,0 +1,121 @@ +/** + * ======================== legal notice ====================== + * + * File: HTTPStatus.cc + * Created: 3. Juli 2012, 17:34 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <HTTPStatus.h> +#include <stdlib.h> + +const char *httpStatus2Text(int Status) +{ + switch (Status) { + case HTTP_Continue: return "Continue"; + case HTTP_SwitchProtocol: return "Gonna switch Protocol"; + case HTTP_OK: return "Ok"; + case HTTP_Created: return "Created"; + case HTTP_Accepted: return "Accepted"; + case HTTP_NoContent: return "No Content"; + case HTTP_ResetContent: return "reset Content"; + case HTTP_PartialContent: return "partial Content"; + case HTTP_MultipleChoices: return "Multiple Choices"; + case HTTP_MovedPermanently: return "Permanently moved"; + case HTTP_Found: return "Found"; + case HTTP_SeeOther: return "See other"; + case HTTP_NotModified: return "Not modified"; + case HTTP_UseProxy: return "Use Proxy"; + case HTTP_MovedTemporarily: return "Temporarily moved"; + case HTTP_BadRequest: return "Bad Request"; + case HTTP_UnAuthorized: return "Unauthorized"; + case HTTP_PaymentRequired: return "Payment required"; + case HTTP_Forbidden: return "Forbidden"; + case HTTP_NotFound: return "Not Found"; + case HTTP_MethodNotAllowed: return "Not Allowed"; + case HTTP_NotAcceptable: return "Not acceptable"; + case HTTP_ProxyAuthenticationRequired: return "Authentication required"; + case HTTP_RequestTimeout: return "Request timed out"; + case HTTP_Conflict: return "Conflict"; + case HTTP_Gone: return "Gone"; + case HTTP_LengthRequired: return "Length required"; + case HTTP_PreconditionFailed: return "Precondition failed"; + case HTTP_RequestTooLarge: return "Request too large"; + case HTTP_RequestURIToLong: return "Requested URI to long"; + case HTTP_UnsupportedMediaType: return "Unsupported Media Type"; + case HTTP_RequestRangeNotSatisfiable: return "Request Range Not satisfiable"; + case HTTP_ExpectationFailed: return "Expectation failed"; + case HTTP_InternalServerError: return "Internal Server Error"; + case HTTP_NotImplemented: return "Not implemented"; + case HTTP_BadGateway: return "Bad Gateway"; + case HTTP_ServiceUnavailable: return "Service unavailable"; + case HTTP_GatewayTimeout: return "Gateway timed out"; + case HTTP_VersionNotSupported: return "Version not supported"; + default: return "Unsupported/Unknown status"; + } +} + +HTTPStatusCode strtoHTTPStatus(const char *p) +{ + int tmp = atoi(p); + + switch (tmp) { + case HTTP_Continue: return HTTP_Continue; + case HTTP_SwitchProtocol: return HTTP_SwitchProtocol; + case HTTP_OK: return HTTP_OK; + case HTTP_Created: return HTTP_Created; + case HTTP_Accepted: return HTTP_Accepted; + case HTTP_NoContent: return HTTP_NoContent; + case HTTP_ResetContent: return HTTP_ResetContent; + case HTTP_PartialContent: return HTTP_PartialContent; + case HTTP_MultipleChoices: return HTTP_MultipleChoices; + case HTTP_MovedPermanently: return HTTP_MovedPermanently; + case HTTP_Found: return HTTP_Found; + case HTTP_SeeOther: return HTTP_SeeOther; + case HTTP_NotModified: return HTTP_NotModified; + case HTTP_UseProxy: return HTTP_UseProxy; + case HTTP_MovedTemporarily: return HTTP_MovedTemporarily; + case HTTP_BadRequest: return HTTP_BadRequest; + case HTTP_UnAuthorized: return HTTP_UnAuthorized; + case HTTP_PaymentRequired: return HTTP_PaymentRequired; + case HTTP_Forbidden: return HTTP_Forbidden; + case HTTP_NotFound: return HTTP_NotFound; + case HTTP_MethodNotAllowed: return HTTP_MethodNotAllowed; + case HTTP_NotAcceptable: return HTTP_NotAcceptable; + case HTTP_ProxyAuthenticationRequired: return HTTP_ProxyAuthenticationRequired; + case HTTP_RequestTimeout: return HTTP_RequestTimeout; + case HTTP_Conflict: return HTTP_Conflict; + case HTTP_Gone: return HTTP_Gone; + case HTTP_LengthRequired: return HTTP_LengthRequired; + case HTTP_PreconditionFailed: return HTTP_PreconditionFailed; + case HTTP_RequestTooLarge: return HTTP_RequestTooLarge; + case HTTP_RequestURIToLong: return HTTP_RequestURIToLong; + case HTTP_UnsupportedMediaType: return HTTP_UnsupportedMediaType; + case HTTP_RequestRangeNotSatisfiable: return HTTP_RequestRangeNotSatisfiable; + case HTTP_ExpectationFailed: return HTTP_ExpectationFailed; + case HTTP_InternalServerError: return HTTP_InternalServerError; + case HTTP_NotImplemented: return HTTP_NotImplemented; + case HTTP_BadGateway: return HTTP_BadGateway; + case HTTP_ServiceUnavailable: return HTTP_ServiceUnavailable; + case HTTP_GatewayTimeout: return HTTP_GatewayTimeout; + case HTTP_VersionNotSupported: return HTTP_VersionNotSupported; + default: return HTTP_InternalServerError; + } +} + diff --git a/libs/networking/src/Principal.cc b/libs/networking/src/Principal.cc new file mode 100644 index 0000000..65103d9 --- /dev/null +++ b/libs/networking/src/Principal.cc @@ -0,0 +1,105 @@ +/** + * ======================== legal notice ====================== + * + * File: Principal.cc + * Created: 3. Juli 2012, 12:50 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <Principal.h> +#include <MD5Calculator.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <util.h> + +cPrincipal::cPrincipal(const char *Name, const char *Realm) + : name(strdup(Name)) + , realm(strdup(Realm)) + , hash(NULL) + , xinfo(NULL) + , age(0) +{ +} + +cPrincipal::cPrincipal(const cPrincipal& other) + : name(other.name ? strdup(other.name) : NULL) + , realm(other.realm ? strdup(other.realm) : NULL) + , hash(other.hash ? strdup(other.hash) : NULL) + , xinfo(other.xinfo ? strdup(other.xinfo) : NULL) + , age(other.age) +{ +} + +cPrincipal::~cPrincipal() +{ + FREE(name); + FREE(realm); + FREE(hash); + FREE(xinfo); +} + +void cPrincipal::CreateHash(const char* Password) +{ + cMD5Calculator hc; + + FREE(hash); + hc.AddContent(name, strlen(name)); + hc.AddContent(":", 1); + hc.AddContent(realm, strlen(realm)); + hc.AddContent(":", 1); + hc.AddContent(Password, strlen(Password)); + + hash = hc.Hash(); +} + +void cPrincipal::SetName(const char* Name) +{ + FREE(name); + name = Name ? strdup(Name) : NULL; +} + +void cPrincipal::SetRealm(const char* Realm) +{ + FREE(realm); + realm = Realm ? strdup(Realm) : NULL; +} + +void cPrincipal::SetHash(const char* Hash) +{ + FREE(hash); + hash = Hash ? strdup(Hash) : NULL; +} + +void cPrincipal::SetExtendedInfo(const char* Info) +{ + FREE(xinfo); + xinfo = Info ? strdup(Info) : NULL; +} + +void cPrincipal::Dump(void) const +{ + printf(">>> ========= Principal ======================\n"); + printf("name ....: >%s<\n", name); + printf("realm ...: >%s<\n", realm); + printf("hash ....: >%s<\n", hash); + printf("age .....: >%d<\n", age); + printf("ext. info: >%s<\n", xinfo); + printf("------------- Principal ------------------ <<<\n"); +} diff --git a/libs/networking/src/ServerConfig.cc b/libs/networking/src/ServerConfig.cc new file mode 100644 index 0000000..e6ad4b8 --- /dev/null +++ b/libs/networking/src/ServerConfig.cc @@ -0,0 +1,60 @@ +/** + * ======================== legal notice ====================== + * + * File: ServerConfig.cc + * Created: 8. Juli 2012, 06:12 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <ServerConfig.h> +#include <Logging.h> +#include <util.h> +#include <sys/stat.h> +#include <sys/types.h> + +cServerConfig::cServerConfig(int Port) + : server(Port, 5) + , documentRoot(NULL) + , appIconPath(NULL) +{ +} + +cServerConfig::~cServerConfig() +{ + FREE(appIconPath); + FREE(documentRoot); +} + +void cServerConfig::SetAppIcon(const char* AppIcon) +{ + struct stat st; + + if (!AppIcon) return; + if (!stat(AppIcon, &st)) { + FREE(appIconPath); + appIconPath = strdup(AppIcon); + } + else esyslog("ERROR: failed to stat application icon! %s", AppIcon); +} + +void cServerConfig::SetDocumentRoot(const char* DocumentRoot) +{ + free(documentRoot); + documentRoot = DocumentRoot ? strdup(DocumentRoot) : NULL; +}
\ No newline at end of file diff --git a/libs/networking/src/ServerSocket.cc b/libs/networking/src/ServerSocket.cc new file mode 100644 index 0000000..2ff92fb --- /dev/null +++ b/libs/networking/src/ServerSocket.cc @@ -0,0 +1,84 @@ +/** + * ======================== legal notice ====================== + * + * File: ServerSocket.cc + * Created: 4. Juli 2012, 07:28 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <ServerSocket.h> +#include <Logging.h> +#include <fcntl.h> + +cServerSocket::cServerSocket(int Port, int Queue) + : cAbstractSocket(Port, Queue) + , port(Port) + , active(true) +{ +} + +cServerSocket::~cServerSocket() +{ +} + +bool cServerSocket::Open(void) +{ + return cAbstractSocket::Open(port); +} + +cConnectionPoint *cServerSocket::Accept(void) +{ + cConnectionPoint *rv = NULL; + + while (active && !rv) { + rv = cAbstractSocket::Accept(port, 500); + } + return rv; +} + +void cServerSocket::ConfigureSocket(int Socket) +{ + if (!ForceBlockingIO()) { + // make it non-blocking: + int oldflags = fcntl(Socket, F_GETFL, 0); + + if (oldflags < 0) { + esyslog("could not retrieve old socket flags"); + + return; + } + + oldflags |= O_NONBLOCK; + if (fcntl(Socket, F_SETFL, oldflags) < 0) { + esyslog("failed to set nonblocking state of socket"); + + return; + } + } +} + +void cServerSocket::SetBlockingIO(bool ForceBlockingIO) +{ + cAbstractSocket::SetBlockingIO(ForceBlockingIO); +} + +bool cServerSocket::ForceBlockingIO() const +{ + return cAbstractSocket::ForceBlockingIO(); +} diff --git a/libs/networking/src/Url.cc b/libs/networking/src/Url.cc new file mode 100644 index 0000000..011d493 --- /dev/null +++ b/libs/networking/src/Url.cc @@ -0,0 +1,229 @@ +/** + * ======================== legal notice ====================== + * + * File: Url.cc + * Created: 4. Juli 2012, 05:42 + * Author: <a href="mailto:geronimo013@gmx.de">Geronimo</a> + * Project: libnetworking: classes for tcp/ip sockets and http-protocol handling + * + * CMP - compound media player + * + * is a client/server mediaplayer intended to play any media from any workstation + * without the need to export or mount shares. cmps is an easy to use backend + * with a (ready to use) HTML-interface. Additionally the backend supports + * authentication via HTTP-digest authorization. + * cmpc is a client with vdr-like osd-menues. + * + * Copyright (c) 2012 Reinhard Mantey, some rights reserved! + * published under Creative Commons by-sa + * For details see http://creativecommons.org/licenses/by-sa/3.0/ + * + * The cmp project's homepage is at http://projects.vdr-developer.org/projects/cmp + * + * -------------------------------------------------------------- + */ +#include <Url.h> +#include <Codec.h> +#include <util.h> +#ifdef DEBUG +#include <iostream> +#endif +#include <stdio.h> +#include <string.h> +#include <vector> + +static cURLEncoder * encoder = NULL; +static cURLDecoder * decoder = NULL; + +cUrl::cUrl(const char* RawURL) + : path(NULL) +{ + ParseURL(RawURL); +} + +cUrl::~cUrl() +{ + FREE(path); +} + +cURLDecoder* cUrl::Decoder(void) const +{ + if (!decoder) decoder = new cURLDecoder(); + return decoder; +} + +cURLEncoder* cUrl::Encoder(void) const +{ + if (!encoder) encoder = new cURLEncoder(); + return encoder; +} + +const char *cUrl::Parameter(const char* Name) +{ + std::tr1::unordered_map<std::string, std::string>::iterator found = parameters.find(Name); + if (found != parameters.end()) return found->second.c_str(); + return NULL; +} + +void cUrl::SetParameter(const char* Name, const char* Value) +{ + std::string name = Name; + std::string value = Value ? Value : " "; + parameters[name] = value; +} + +size_t cUrl::EstimatedSize(void ) const +{ + size_t rv = parameters.size() * 3; + + if (path) rv += strlen(path) + 4; + ParameterMap::const_iterator pm = parameters.begin(); + + while (pm != parameters.end()) { + rv += pm->first.length() * 3; + rv += pm->second.length() * 3; + ++pm; + } + return rv; +} + +void cUrl::ParseURL(const char *URL) +{ + FREE(path); + parameters.clear(); + if (!URL) return; + const char *q = strchr(URL, '?'); // divider between url and querystring +// char *realURL; +// size_t l; + + if (!q) q = URL + strlen(URL); +// l = q - URL; +// realURL = (char *)malloc(l + 2); +// if (!realURL) return; +// strncpy(realURL, URL, l); +// realURL[l] = 0; + path = Decoder()->Decode(URL, q - URL); + if (*q) ParseQueryString(++q); +} + +void cUrl::ParseQueryString(const char* QueryString) +{ + if (!(QueryString && *QueryString)) return; + const char *start, *last; + char *scratch = strdup(QueryString); + char *p, *end; + size_t srcLen = strlen(QueryString); + + for (start = (const char *)scratch, end = (char *) start, last = scratch + srcLen; end && start < last; start = (const char *)++end) { + end = (char *) strchr(start, '&'); + if (!end) end = (char *)start + strlen(start); + *end = 0; + p = (char *) strchr(start, '='); + if (p) { + *p++ = 0; + char *pn = p ? Decoder()->Decode(start) : NULL; + char *pv = p ? Decoder()->Decode(p) : NULL; + + std::string name = pn; + std::string value = pv ? pv : " "; + + parameters[name] = value; + + free(pn); + free(pv); + } + else { + char *pn = Decoder()->Decode(start); + + std::string name = pn; + parameters[name] = " "; + free(pn); + } + } + free(scratch); +} + +char* cUrl::ToString(void) const +///< returns the address of the newly allocated buffer +{ + size_t bufSize = EstimatedSize(); + char *rv = (char *)malloc(bufSize); + + if (!rv) return NULL; + int n = WriteBuf(rv, bufSize); + + if (n < 0) { + bufSize += 128; + rv = (char *) realloc(rv, bufSize); + WriteBuf(rv, bufSize); + } + return rv; +} + +int cUrl::WriteBuf(char* buf, size_t bufSize) const +///< returns the characters written. -1 as return value indicates a buffer overrun. +{ + char *p, *tmp; + bool first = true; + int n = 0; + + if (path) n += snprintf(buf + n, bufSize - n, "%s", path); + p = buf + n; + ParameterMap::const_iterator pm = parameters.begin(); + + while (pm != parameters.end()) { + tmp = Encoder()->Encode(pm->first.c_str()); + if (p - buf + strlen(tmp) + 2 > bufSize) + return -1; + if (first) { + first = false; + *p++ = '?'; + } + else *p++ = '&'; + strcpy(p, tmp); + p += strlen(p); + FREE(tmp); + + if (strcmp(pm->second.c_str(), " ")) { + tmp = Encoder()->Encode(pm->second.c_str()); + if (p - buf + strlen(tmp) + 2 > bufSize) + return -1; + *p++ = '='; + strcpy(p, tmp); + p += strlen(p); + FREE(tmp); + } + ++pm; + } + p += strlen(p); + + return p - buf; +} + +#ifdef DEBUG +void cUrl::Dump(void ) +{ + ParameterMap::const_iterator pm = parameters.begin(); + + while (pm != parameters.end()) { + std::cout << "parameter [" << pm->first << "]"; + if (strcmp(pm->second.c_str(), " ")) + std::cout << " has value <|" << pm->second << "|>" << std::endl; + else + std::cout << " has NO value!" << std::endl; + ++pm; + } +} +#endif + +void cUrl::Cleanup(void ) +{ + if (encoder) { + delete encoder; + encoder = NULL; + } + if (decoder) { + delete decoder; + decoder = NULL; + } +}
\ No newline at end of file diff --git a/libs/networking/summary.txt b/libs/networking/summary.txt new file mode 100644 index 0000000..5e47f27 --- /dev/null +++ b/libs/networking/summary.txt @@ -0,0 +1 @@ +libnetworking: classes for tcp/ip sockets and http-protocol handling |