diff --git a/uppsrc/Core/Debug.cpp b/uppsrc/Core/Debug.cpp index 75c9b0dfd..ebd81da88 100644 --- a/uppsrc/Core/Debug.cpp +++ b/uppsrc/Core/Debug.cpp @@ -4,8 +4,6 @@ NAMESPACE_UPP #define LTIMING(x) // TIMING(x) -int msecs(int from) { return (int)GetTickCount() - from; } - #ifdef PLATFORM_WIN32 #include #endif diff --git a/uppsrc/Core/Diag.h b/uppsrc/Core/Diag.h index e12b35307..0bddd5fc2 100644 --- a/uppsrc/Core/Diag.h +++ b/uppsrc/Core/Diag.h @@ -73,8 +73,6 @@ void CloseStdLog(); void HexDump(Stream& s, const void *ptr, int size, int maxsize = INT_MAX); -int msecs(int from = 0); - String GetTypeName(const char *type_name); inline String GetTypeName(const ::std::type_info& tinfo) { return GetTypeName(tinfo.name()); } diff --git a/uppsrc/Core/Inet.h b/uppsrc/Core/Inet.h index ff284d734..2bd99fc25 100644 --- a/uppsrc/Core/Inet.h +++ b/uppsrc/Core/Inet.h @@ -1,3 +1,4 @@ +String WwwFormat(Time tm); String FormatIP(dword _ip); String UrlEncode(const String& s); @@ -81,7 +82,7 @@ class TcpSocket { struct SSL { virtual bool Start() = 0; - virtual bool Wait(dword flags) = 0; + virtual bool Wait(dword flags, int end_time) = 0; virtual int Send(const void *buffer, int maxlen) = 0; virtual int Recv(void *buffer, int maxlen) = 0; virtual void Close() = 0; @@ -92,7 +93,9 @@ class TcpSocket { One ssl; One sslinfo; - + String cert, pkey; + bool asn1; + struct SSLImp; friend struct SSLImp; @@ -101,7 +104,9 @@ class TcpSocket { friend void InitCreateSSL(); - bool RawWait(dword flags); + int GetEndTime() const; + bool RawWait(dword flags, int end_time); + bool Wait(dword events, int end_time); SOCKET AcceptRaw(dword *ipaddr, int timeout_msec); bool Open(int family, int type, int protocol); int RawRecv(void *buffer, int maxlen); @@ -111,9 +116,11 @@ class TcpSocket { bool RawConnect(addrinfo *info); void RawClose(); - void ReadBuffer(); + void ReadBuffer(int end_time); int Get_(); int Peek_(); + int Peek_(int end_time); + int Peek(int end_time) { return ptr < end ? *ptr : Peek_(end_time); } void Reset(); @@ -170,18 +177,21 @@ public: int Get() { return ptr < end ? *ptr++ : Get_(); } int Get(void *buffer, int len); String Get(int len); - int GetAll(void *buffer, int len) { return Get(buffer, len) == len; } - String GetAll(int len); - String GetLine(int maxlen = 2000000); int Put(const char *s, int len); int Put(const String& s) { return Put(s.Begin(), s.GetLength()); } - bool PutAll(const char *s, int len) { return Put(s, len) == len; } - bool PutAll(const String& s) { return Put(s) == s.GetCount(); } + + bool GetAll(void *buffer, int len); + String GetAll(int len); + String GetLine(int maxlen = 65536); + + bool PutAll(const char *s, int len); + bool PutAll(const String& s); bool StartSSL(); bool IsSSL() const { return ssl; } bool SSLHandshake(); + void SSLCertificate(const String& cert, const String& pkey, bool asn1); const SSLInfo *GetSSLInfo() const { return ~sslinfo; } TcpSocket& Timeout(int ms) { timeout = ms; return *this; } diff --git a/uppsrc/Core/InetUtil.cpp b/uppsrc/Core/InetUtil.cpp index 4099c0210..5c52cabb8 100644 --- a/uppsrc/Core/InetUtil.cpp +++ b/uppsrc/Core/InetUtil.cpp @@ -2,6 +2,19 @@ NAMESPACE_UPP +String WwwFormat(Time tm) +{ + static const char *dayofweek[] = + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + static const char *month[] = + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return String().Cat() + << dayofweek[DayOfWeek(tm)] << ", " + << (int)tm.day << ' ' << month[tm.month - 1] + << ' ' << (int)tm.year + << ' ' << Sprintf("%2d:%02d:%02d +0100", tm.hour, tm.minute, tm.second); +} + String FormatIP(dword _ip) { byte ip[4]; diff --git a/uppsrc/Core/SSL/SSL.h b/uppsrc/Core/SSL/SSL.h index deced43cd..cf1bd217d 100644 --- a/uppsrc/Core/SSL/SSL.h +++ b/uppsrc/Core/SSL/SSL.h @@ -1,136 +1,136 @@ -#include - -#include -#include -#include -#include - -NAMESPACE_UPP - -void SslInitThread(); - -class SslBuffer -{ -public: - SslBuffer(BUF_MEM *m = NULL) : buf_mem(m) {} - ~SslBuffer() { Clear(); } - - bool IsEmpty() const { return !buf_mem; } - - bool Set(BUF_MEM *b) { Clear(); return !!(buf_mem = b); } - bool Create() { return Set(BUF_MEM_new()); } - void Clear() { if(buf_mem) { BUF_MEM_free(buf_mem); buf_mem = NULL; } } - BUF_MEM *Detach() { BUF_MEM *b = buf_mem; buf_mem = NULL; return b; } - - bool Grow(int length); - - String Get() const; - bool Set(const String& d); - - operator BUF_MEM * () const { return buf_mem; } - -private: - BUF_MEM *buf_mem; -}; - -class SslStream -{ -public: - SslStream(BIO *b = NULL) : bio(b) {} - ~SslStream() { Clear(); } - - bool IsEmpty() const { return !bio; } - - bool Set(BIO *b) { Clear(); return !!(bio = b); } - bool Create(BIO_METHOD *meth) { return Set(BIO_new(meth)); } - void Clear() { if(bio) { BIO_free(bio); bio = NULL; } } - - bool OpenBuffer(const char *data, int length); - bool CreateBuffer(); - String GetResult() const; - - operator BIO * () const { return bio; } - -private: - BIO *bio; -}; - -class SslKey -{ -public: - SslKey(EVP_PKEY *k = NULL) : key(k) {} - ~SslKey() { Clear(); } - - bool IsEmpty() const { return !key; } - - bool Set(EVP_PKEY *k) { Clear(); return !!(key = k); } - void Clear() { if(key) { EVP_PKEY_free(key); key = NULL; } } - EVP_PKEY *Detach() { EVP_PKEY *k = key; key = NULL; return k; } - - operator EVP_PKEY * () const { return key; } - - bool Load(const String& data); - -private: - EVP_PKEY *key; -}; - -class SslCertificate -{ -public: - SslCertificate(X509 *c = NULL) : cert(c) {} - ~SslCertificate() { Clear(); } - - bool IsEmpty() const { return !cert; } - - bool Set(X509 *c) { Clear(); return !!(cert = c); } - bool Create() { return Set(X509_new()); } - void Clear() { if(cert) { X509_free(cert); cert = NULL; } } - X509 *Detach() { X509 *c = cert; cert = NULL; return c; } - - bool Load(const String& data, bool asn1 = false); - String Save(bool asn1 = false) const; - - String GetSubjectName() const; - String GetIssuerName() const; - Date GetNotBefore() const; - Date GetNotAfter() const; - int GetVersion() const; - String GetSerialNumber() const; - - operator X509 * () const { return cert; } - -private: - X509 *cert; -}; - -class SslContext -{ -public: - SslContext(SSL_CTX *c = NULL); - ~SslContext() { Clear(); } - - bool IsEmpty() const { return !ssl_ctx; } - - bool Set(SSL_CTX *c) { Clear(); return !!(ssl_ctx = c); } - bool Create(SSL_METHOD *meth) { return Set(SSL_CTX_new(meth)); } - void Clear() { if(ssl_ctx) { SSL_CTX_free(ssl_ctx); ssl_ctx = NULL; } } - SSL_CTX *Detach() { SSL_CTX *c = ssl_ctx; ssl_ctx = NULL; return c; } - - operator SSL_CTX * () const { return ssl_ctx; } - - bool CipherList(const char *list); - bool UseCertificate(String certificate, String private_key, bool cert_asn1 = false); - void VerifyPeer(bool verify = true, int depth = 2); - -private: - SSL_CTX *ssl_ctx; -}; - -String SslGetLastError(int& code); -String SslGetLastError(); -String SslToString(X509_NAME *name); -Date ASN1ToDate(ASN1_STRING *time); -String ASN1ToString(ASN1_STRING *s); - -END_UPP_NAMESPACE +#include + +#include +#include +#include +#include + +NAMESPACE_UPP + +void SslInitThread(); + +class SslBuffer +{ +public: + SslBuffer(BUF_MEM *m = NULL) : buf_mem(m) {} + ~SslBuffer() { Clear(); } + + bool IsEmpty() const { return !buf_mem; } + + bool Set(BUF_MEM *b) { Clear(); return !!(buf_mem = b); } + bool Create() { return Set(BUF_MEM_new()); } + void Clear() { if(buf_mem) { BUF_MEM_free(buf_mem); buf_mem = NULL; } } + BUF_MEM *Detach() { BUF_MEM *b = buf_mem; buf_mem = NULL; return b; } + + bool Grow(int length); + + String Get() const; + bool Set(const String& d); + + operator BUF_MEM * () const { return buf_mem; } + +private: + BUF_MEM *buf_mem; +}; + +class SslStream +{ +public: + SslStream(BIO *b = NULL) : bio(b) {} + ~SslStream() { Clear(); } + + bool IsEmpty() const { return !bio; } + + bool Set(BIO *b) { Clear(); return !!(bio = b); } + bool Create(BIO_METHOD *meth) { return Set(BIO_new(meth)); } + void Clear() { if(bio) { BIO_free(bio); bio = NULL; } } + + bool OpenBuffer(const char *data, int length); + bool CreateBuffer(); + String GetResult() const; + + operator BIO * () const { return bio; } + +private: + BIO *bio; +}; + +class SslKey +{ +public: + SslKey(EVP_PKEY *k = NULL) : key(k) {} + ~SslKey() { Clear(); } + + bool IsEmpty() const { return !key; } + + bool Set(EVP_PKEY *k) { Clear(); return !!(key = k); } + void Clear() { if(key) { EVP_PKEY_free(key); key = NULL; } } + EVP_PKEY *Detach() { EVP_PKEY *k = key; key = NULL; return k; } + + operator EVP_PKEY * () const { return key; } + + bool Load(const String& data); + +private: + EVP_PKEY *key; +}; + +class SslCertificate +{ +public: + SslCertificate(X509 *c = NULL) : cert(c) {} + ~SslCertificate() { Clear(); } + + bool IsEmpty() const { return !cert; } + + bool Set(X509 *c) { Clear(); return !!(cert = c); } + bool Create() { return Set(X509_new()); } + void Clear() { if(cert) { X509_free(cert); cert = NULL; } } + X509 *Detach() { X509 *c = cert; cert = NULL; return c; } + + bool Load(const String& data, bool asn1 = false); + String Save(bool asn1 = false) const; + + String GetSubjectName() const; + String GetIssuerName() const; + Date GetNotBefore() const; + Date GetNotAfter() const; + int GetVersion() const; + String GetSerialNumber() const; + + operator X509 * () const { return cert; } + +private: + X509 *cert; +}; + +class SslContext +{ +public: + SslContext(SSL_CTX *c = NULL); + ~SslContext() { Clear(); } + + bool IsEmpty() const { return !ssl_ctx; } + + bool Set(SSL_CTX *c) { Clear(); return !!(ssl_ctx = c); } + bool Create(SSL_METHOD *meth) { return Set(SSL_CTX_new(meth)); } + void Clear() { if(ssl_ctx) { SSL_CTX_free(ssl_ctx); ssl_ctx = NULL; } } + SSL_CTX *Detach() { SSL_CTX *c = ssl_ctx; ssl_ctx = NULL; return c; } + + operator SSL_CTX * () const { return ssl_ctx; } + + bool CipherList(const char *list); + bool UseCertificate(String certificate, String private_key, bool cert_asn1 = false); + void VerifyPeer(bool verify = true, int depth = 2); + +private: + SSL_CTX *ssl_ctx; +}; + +String SslGetLastError(int& code); +String SslGetLastError(); +String SslToString(X509_NAME *name); +Date Asn1ToDate(ASN1_STRING *time); +String Asn1ToString(ASN1_STRING *s); + +END_UPP_NAMESPACE diff --git a/uppsrc/Core/SSL/Socket.cpp b/uppsrc/Core/SSL/Socket.cpp index da56b0e69..ceedf7f6e 100644 --- a/uppsrc/Core/SSL/Socket.cpp +++ b/uppsrc/Core/SSL/Socket.cpp @@ -6,7 +6,7 @@ NAMESPACE_UPP struct TcpSocket::SSLImp : TcpSocket::SSL { virtual bool Start(); - virtual bool Wait(dword flags); + virtual bool Wait(dword flags, int end_time); virtual int Send(const void *buffer, int maxlen); virtual int Recv(void *buffer, int maxlen); virtual void Close(); @@ -109,7 +109,8 @@ bool TcpSocket::SSLImp::Start() SetSSLError("Start: SSL context."); return false; } -// context.VerifyPeer(); + if(socket.cert.GetCount()) + context.UseCertificate(socket.cert, socket.pkey, socket.asn1); if(!(ssl = SSL_new(context))) { SetSSLError("Start: SSL_new"); return false; @@ -157,12 +158,12 @@ dword TcpSocket::SSLImp::Handshake() return 0; } -bool TcpSocket::SSLImp::Wait(dword flags) +bool TcpSocket::SSLImp::Wait(dword flags, int end_time) { LLOG("SSL Wait"); if((flags & WAIT_READ) && SSL_pending(ssl) > 0) return true; - return socket.RawWait(flags); + return socket.RawWait(flags, end_time); } int TcpSocket::SSLImp::Send(const void *buffer, int maxlen) diff --git a/uppsrc/Core/SSL/Util.cpp b/uppsrc/Core/SSL/Util.cpp index 8e8582d05..f26fdcfdb 100644 --- a/uppsrc/Core/SSL/Util.cpp +++ b/uppsrc/Core/SSL/Util.cpp @@ -1,208 +1,208 @@ -#include "SSL.h" - -NAMESPACE_UPP - -String SslBuffer::Get() const -{ - if(IsEmpty()) - return String::GetVoid(); - return String(buf_mem->data, buf_mem->length); -} - -bool SslBuffer::Grow(int length) -{ - return !IsEmpty() && BUF_MEM_grow(buf_mem, length); -} - -bool SslBuffer::Set(const String& d) -{ - if(!buf_mem && !Create()) - return false; - int len = d.GetLength(); - if((int)buf_mem->max < len && !Grow(len)) - return false; - ASSERT((int)buf_mem->max >= len); - buf_mem->length = len; - memcpy(buf_mem, d, len); - return true; -} - -bool SslStream::OpenBuffer(const char *data, int length) -{ - return Set(BIO_new_mem_buf(const_cast(data), length)); -} - -bool SslStream::CreateBuffer() -{ - Clear(); - SslBuffer buf; - if(!buf.Create() || !Create(BIO_s_mem())) - return false; - BIO_set_mem_buf(bio, buf.Detach(), BIO_CLOSE); - return true; -} - -String SslStream::GetResult() const -{ - if(IsEmpty()) - return String::GetVoid(); - BUF_MEM *bm = NULL; - BIO_get_mem_ptr(bio, &bm); - if(!bm) - return String::GetVoid(); - return String(bm->data, bm->length); -} - -bool SslKey::Load(const String& data) -{ - Clear(); - SslStream strm; - if(!strm.OpenBuffer(data.Begin(), data.GetLength())) - return false; - return Set(PEM_read_bio_PrivateKey(strm, NULL, NULL, NULL)); -} - -bool SslCertificate::Load(const String& data, bool asn1) -{ - Clear(); - SslStream in, pem, *sio = ∈ - if(!in.OpenBuffer(data, data.GetLength())) - return false; - if(!asn1) - { - if(!pem.Create(BIO_f_base64())) - return false; - BIO_push(pem, in); - sio = &pem; - } - return Set(d2i_X509_bio(*sio, NULL)); -} - -String SslCertificate::Save(bool asn1) const -{ - if(IsEmpty()) - return String::GetVoid(); - SslStream out, pem, *sio = &out; - if(!out.CreateBuffer()) - return String::GetVoid(); - if(!asn1) - { - if(!pem.Create(BIO_f_base64())) - return String::GetVoid(); - BIO_push(pem, out); - sio = &pem; - } - i2d_X509_bio(*sio, cert); - return out.GetResult(); -} - -String SslCertificate::GetSubjectName() const -{ - ASSERT(!IsEmpty()); - return SslToString(X509_get_subject_name(cert)); -} - -String SslCertificate::GetIssuerName() const -{ - ASSERT(!IsEmpty()); - return SslToString(X509_get_issuer_name(cert)); -} - -Date SslCertificate::GetNotBefore() const -{ - ASSERT(!IsEmpty()); - return ASN1ToDate(X509_get_notBefore(cert)); -} - -Date SslCertificate::GetNotAfter() const -{ - ASSERT(!IsEmpty()); - return ASN1ToDate(X509_get_notAfter(cert)); -} - -int SslCertificate::GetVersion() const -{ - ASSERT(!IsEmpty()); - return X509_get_version(cert); -} - -String SslCertificate::GetSerialNumber() const -{ - ASSERT(!IsEmpty()); - return ASN1ToString(X509_get_serialNumber(cert)); -} - -SslContext::SslContext(SSL_CTX *c) -: ssl_ctx(c) -{ - SslInitThread(); -} - -bool SslContext::CipherList(const char *list) -{ - ASSERT(ssl_ctx); - return SSL_CTX_set_cipher_list(ssl_ctx, list); -} - -bool SslContext::UseCertificate(String certdata, String pkeydata, bool cert_asn1) -{ - ASSERT(ssl_ctx); - if(IsNull(certdata) || IsNull(pkeydata)) - return false; - SslCertificate cert; - SslKey pkey; - if(!cert.Load(certdata, cert_asn1) || !pkey.Load(pkeydata)) - return false; - if(!SSL_CTX_use_certificate(ssl_ctx, cert) || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey)) - return false; - if(!SSL_CTX_check_private_key(ssl_ctx)) - return false; - return true; -} - -void SslContext::VerifyPeer(bool verify, int depth) -{ - ASSERT(ssl_ctx); - SSL_CTX_set_verify(ssl_ctx, verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); - SSL_CTX_set_verify_depth(ssl_ctx, depth); -} - -String SslGetLastError(int& code) -{ - char errbuf[150]; - ERR_error_string(code = ERR_get_error(), errbuf); - return errbuf; -} - -String SslGetLastError() -{ - int dummy; - return SslGetLastError(dummy); -} - -String SslToString(X509_NAME *name) -{ - char buffer[500]; - return X509_NAME_oneline(name, buffer, sizeof(buffer)); -} - -Date ASN1ToDate(ASN1_STRING *time) -{ - if(!time) return Null; - int digit = 0; - while(digit < time->length && IsDigit(time->data[digit])) - digit++; - if(digit < 6) - return Null; - int year2 = time->data[0] * 10 + time->data[1] - 11 * '0'; - int month = time->data[2] * 10 + time->data[3] - 11 * '0'; - int day = time->data[4] * 10 + time->data[5] - 11 * '0'; - return Date(year2 + (year2 < 90 ? 2000 : 1900), month, day); -} - -String ASN1ToString(ASN1_STRING *s) -{ - return String(s->data, s->length); -} - -END_UPP_NAMESPACE +#include "SSL.h" + +NAMESPACE_UPP + +String SslBuffer::Get() const +{ + if(IsEmpty()) + return String::GetVoid(); + return String(buf_mem->data, buf_mem->length); +} + +bool SslBuffer::Grow(int length) +{ + return !IsEmpty() && BUF_MEM_grow(buf_mem, length); +} + +bool SslBuffer::Set(const String& d) +{ + if(!buf_mem && !Create()) + return false; + int len = d.GetLength(); + if((int)buf_mem->max < len && !Grow(len)) + return false; + ASSERT((int)buf_mem->max >= len); + buf_mem->length = len; + memcpy(buf_mem, d, len); + return true; +} + +bool SslStream::OpenBuffer(const char *data, int length) +{ + return Set(BIO_new_mem_buf(const_cast(data), length)); +} + +bool SslStream::CreateBuffer() +{ + Clear(); + SslBuffer buf; + if(!buf.Create() || !Create(BIO_s_mem())) + return false; + BIO_set_mem_buf(bio, buf.Detach(), BIO_CLOSE); + return true; +} + +String SslStream::GetResult() const +{ + if(IsEmpty()) + return String::GetVoid(); + BUF_MEM *bm = NULL; + BIO_get_mem_ptr(bio, &bm); + if(!bm) + return String::GetVoid(); + return String(bm->data, bm->length); +} + +bool SslKey::Load(const String& data) +{ + Clear(); + SslStream strm; + if(!strm.OpenBuffer(data.Begin(), data.GetLength())) + return false; + return Set(PEM_read_bio_PrivateKey(strm, NULL, NULL, NULL)); +} + +bool SslCertificate::Load(const String& data, bool asn1) +{ + Clear(); + SslStream in, pem, *sio = ∈ + if(!in.OpenBuffer(data, data.GetLength())) + return false; + if(!asn1) + { + if(!pem.Create(BIO_f_base64())) + return false; + BIO_push(pem, in); + sio = &pem; + } + return Set(d2i_X509_bio(*sio, NULL)); +} + +String SslCertificate::Save(bool asn1) const +{ + if(IsEmpty()) + return String::GetVoid(); + SslStream out, pem, *sio = &out; + if(!out.CreateBuffer()) + return String::GetVoid(); + if(!asn1) + { + if(!pem.Create(BIO_f_base64())) + return String::GetVoid(); + BIO_push(pem, out); + sio = &pem; + } + i2d_X509_bio(*sio, cert); + return out.GetResult(); +} + +String SslCertificate::GetSubjectName() const +{ + ASSERT(!IsEmpty()); + return SslToString(X509_get_subject_name(cert)); +} + +String SslCertificate::GetIssuerName() const +{ + ASSERT(!IsEmpty()); + return SslToString(X509_get_issuer_name(cert)); +} + +Date SslCertificate::GetNotBefore() const +{ + ASSERT(!IsEmpty()); + return Asn1ToDate(X509_get_notBefore(cert)); +} + +Date SslCertificate::GetNotAfter() const +{ + ASSERT(!IsEmpty()); + return Asn1ToDate(X509_get_notAfter(cert)); +} + +int SslCertificate::GetVersion() const +{ + ASSERT(!IsEmpty()); + return X509_get_version(cert); +} + +String SslCertificate::GetSerialNumber() const +{ + ASSERT(!IsEmpty()); + return Asn1ToString(X509_get_serialNumber(cert)); +} + +SslContext::SslContext(SSL_CTX *c) +: ssl_ctx(c) +{ + SslInitThread(); +} + +bool SslContext::CipherList(const char *list) +{ + ASSERT(ssl_ctx); + return SSL_CTX_set_cipher_list(ssl_ctx, list); +} + +bool SslContext::UseCertificate(String certdata, String pkeydata, bool cert_asn1) +{ + ASSERT(ssl_ctx); + if(IsNull(certdata) || IsNull(pkeydata)) + return false; + SslCertificate cert; + SslKey pkey; + if(!cert.Load(certdata, cert_asn1) || !pkey.Load(pkeydata)) + return false; + if(!SSL_CTX_use_certificate(ssl_ctx, cert) || !SSL_CTX_use_PrivateKey(ssl_ctx, pkey)) + return false; + if(!SSL_CTX_check_private_key(ssl_ctx)) + return false; + return true; +} + +void SslContext::VerifyPeer(bool verify, int depth) +{ + ASSERT(ssl_ctx); + SSL_CTX_set_verify(ssl_ctx, verify ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + SSL_CTX_set_verify_depth(ssl_ctx, depth); +} + +String SslGetLastError(int& code) +{ + char errbuf[150]; + ERR_error_string(code = ERR_get_error(), errbuf); + return errbuf; +} + +String SslGetLastError() +{ + int dummy; + return SslGetLastError(dummy); +} + +String SslToString(X509_NAME *name) +{ + char buffer[500]; + return X509_NAME_oneline(name, buffer, sizeof(buffer)); +} + +Date Asn1ToDate(ASN1_STRING *time) +{ + if(!time) return Null; + int digit = 0; + while(digit < time->length && IsDigit(time->data[digit])) + digit++; + if(digit < 6) + return Null; + int year2 = time->data[0] * 10 + time->data[1] - 11 * '0'; + int month = time->data[2] * 10 + time->data[3] - 11 * '0'; + int day = time->data[4] * 10 + time->data[5] - 11 * '0'; + return Date(year2 + (year2 < 90 ? 2000 : 1900), month, day); +} + +String Asn1ToString(ASN1_STRING *s) +{ + return String(s->data, s->length); +} + +END_UPP_NAMESPACE diff --git a/uppsrc/Core/Socket.cpp b/uppsrc/Core/Socket.cpp index e8e310265..b7eaf1eb9 100644 --- a/uppsrc/Core/Socket.cpp +++ b/uppsrc/Core/Socket.cpp @@ -272,6 +272,7 @@ TcpSocket::TcpSocket() Reset(); timeout = Null; waitstep = 20; + asn1 = false; } bool TcpSocket::Open(int family, int type, int protocol) @@ -343,9 +344,14 @@ bool TcpSocket::Accept(TcpSocket& ls) Close(); Init(); Reset(); - - if(timeout && !ls.WaitRead()) - return false; + ASSERT(ls.IsOpen()); + if(timeout) { + int h = ls.GetTimeout(); + bool b = ls.Timeout(timeout).Wait(WAIT_READ, GetEndTime()); + ls.Timeout(h); + if(!b) + return false; + } if(!Open(ls.ipv6 ? AF_INET6 : AF_INET, SOCK_STREAM, 0)) return false; socket = accept(ls.GetSOCKET(), NULL, NULL); @@ -519,12 +525,11 @@ String TcpSocket::GetHostName() return buffer; } -bool TcpSocket::RawWait(dword flags) +bool TcpSocket::RawWait(dword flags, int end_time) { - LLOG("Wait(" << timeout << ", " << flags << ")"); + LLOG("Wait(" << msecs() << " - " << end_time << ", " << flags << ")"); if((flags & WAIT_READ) && ptr != end) return true; - int end_time = msecs() + timeout; if(socket == INVALID_SOCKET) return false; for(;;) { @@ -564,9 +569,19 @@ bool TcpSocket::RawWait(dword flags) } } +bool TcpSocket::Wait(dword flags, int end_time) +{ + return ssl ? ssl->Wait(flags, end_time) : RawWait(flags, end_time); +} + +int TcpSocket::GetEndTime() const +{ + return IsNull(timeout) ? INT_MAX : msecs() + timeout; +} + bool TcpSocket::Wait(dword flags) { - return ssl ? ssl->Wait(flags) : RawWait(flags); + return Wait(flags, GetEndTime()); } int TcpSocket::Put(const char *s, int length) @@ -579,8 +594,9 @@ int TcpSocket::Put(const char *s, int length) return 0; done = 0; bool peek = false; + int end_time = GetEndTime(); while(done < length) { - if(peek && !WaitWrite()) + if(peek && !Wait(WAIT_WRITE, end_time)) return done; peek = false; int count = Send(s + done, length - done); @@ -595,6 +611,26 @@ int TcpSocket::Put(const char *s, int length) return done; } +bool TcpSocket::PutAll(const char *s, int len) +{ + if(Put(s, len) != len) { + if(!IsError()) + SetSockError("GePutAll", -1, "timeout"); + return false; + } + return true; +} + +bool TcpSocket::PutAll(const String& s) +{ + if(Put(s) != s.GetCount()) { + if(!IsError()) + SetSockError("GePutAll", -1, "timeout"); + return false; + } + return true; +} + int TcpSocket::RawRecv(void *buf, int amount) { int res = recv(socket, (char *)buf, amount, 0); @@ -619,10 +655,10 @@ int TcpSocket::Recv(void *buffer, int maxlen) return ssl ? ssl->Recv(buffer, maxlen) : RawRecv(buffer, maxlen); } -void TcpSocket::ReadBuffer() +void TcpSocket::ReadBuffer(int end_time) { ptr = end = buffer; - if(WaitRead()) + if(Wait(WAIT_READ, end_time)) end = buffer + Recv(buffer, BUFFERSIZE); } @@ -630,16 +666,21 @@ int TcpSocket::Get_() { if(!IsOpen() || IsError() || IsEof() || IsAbort()) return -1; - ReadBuffer(); + ReadBuffer(GetEndTime()); return ptr < end ? *ptr++ : -1; } +int TcpSocket::Peek_(int end_time) +{ + if(!IsOpen() || IsError() || IsEof() || IsAbort()) + return -1; + ReadBuffer(end_time); + return ptr < end ? *ptr : -1; +} + int TcpSocket::Peek_() { - if(!IsOpen() || IsError() || IsEof() || IsAbort()) - return -1; - ReadBuffer(); - return ptr < end ? *ptr : -1; + return Peek_(GetEndTime()); } int TcpSocket::Get(void *buffer, int count) @@ -663,8 +704,9 @@ int TcpSocket::Get(void *buffer, int count) ptr += count; return count; } + int end_time = GetEndTime(); while(done < count && !IsError() && !IsEof()) { - if(!WaitRead()) + if(!Wait(WAIT_READ, end_time)) break; int part = Recv((char *)buffer + done, count - done); if(part > 0) @@ -687,19 +729,41 @@ String TcpSocket::Get(int count) return out; } +bool TcpSocket::GetAll(void *buffer, int len) +{ + if(Get(buffer, len) == len) + return true; + if(!IsError()) + SetSockError("GetAll", -1, "timeout"); + return false; +} + String TcpSocket::GetAll(int len) { String s = Get(len); - return s.GetCount() == len ? s : String::GetVoid(); + if(s.GetCount() != len) { + if(IsEof()) + return s; + if(!IsError()) + SetSockError("GetAll", -1, "timeout"); + return String::GetVoid(); + } + return s; } String TcpSocket::GetLine(int maxlen) { String ln; + int end_time = GetEndTime(); for(;;) { - int c = Peek(); - if(c < 0) + int c = Peek(end_time); + if(c < 0) { + if(IsEof()) + return ln; + if(!IsError()) + SetSockError("GetLine", -1, "timeout"); return String::GetVoid(); + } Get(); if(c == '\n') return ln; @@ -767,6 +831,13 @@ bool TcpSocket::SSLHandshake() return false; } +void TcpSocket::SSLCertificate(const String& cert_, const String& pkey_, bool asn1_) +{ + cert = cert_; + pkey = pkey_; + asn1 = asn1_; +} + int SocketWaitEvent::Wait(int timeout) { FD_ZERO(read); diff --git a/uppsrc/Core/Util.cpp b/uppsrc/Core/Util.cpp index b1e87bcb8..1027b58bd 100644 --- a/uppsrc/Core/Util.cpp +++ b/uppsrc/Core/Util.cpp @@ -125,6 +125,9 @@ dword GetTickCount() { gettimeofday(tv, tz); return (dword)tv->tv_sec * 1000 + tv->tv_usec / 1000; } + +int msecs(int from) { return int((GetTickCount() - (dword)from) & 0x7fffffff); } + #endif void TimeStop::Reset() diff --git a/uppsrc/Core/Util.h b/uppsrc/Core/Util.h index 72fd2f12f..1c3d5a84f 100644 --- a/uppsrc/Core/Util.h +++ b/uppsrc/Core/Util.h @@ -9,6 +9,8 @@ static const int _MAX_PATH = PATH_MAX; dword GetTickCount(); #endif +int msecs(int from = 0); + class TimeStop : Moveable { dword starttime; diff --git a/uppsrc/Web/util.cpp b/uppsrc/Web/util.cpp index ab9fc36d0..cba26b044 100644 --- a/uppsrc/Web/util.cpp +++ b/uppsrc/Web/util.cpp @@ -2,19 +2,6 @@ NAMESPACE_UPP -String WwwFormat(Time tm) -{ - static const char *dayofweek[] = - { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; - static const char *month[] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - return String().Cat() - << dayofweek[DayOfWeek(tm)] << ", " - << (int)tm.day << ' ' << month[tm.month - 1] - << ' ' << (int)tm.year - << ' ' << Sprintf("%2d:%02d:%02d +0100", tm.hour, tm.minute, tm.second); -} - bool IsSameTextFile(const char *p, const char *q) { for(;;) diff --git a/uppsrc/Web/util.h b/uppsrc/Web/util.h index be775b835..35cff57cd 100644 --- a/uppsrc/Web/util.h +++ b/uppsrc/Web/util.h @@ -1,7 +1,6 @@ #ifndef __tweb_util__ #define __tweb_util__ -String WwwFormat(Time tm); bool IsSameTextFile(const char *p, const char *q); String StringSample(const char *s, int limit); String GetRandomIdent(int length);