Kaidul

NSsocket.mm

Nov 20th, 2014
250
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 23.79 KB | None | 0 0
  1. //
  2. //  NSsocket.cpp
  3. //  PAL
  4. //
  5. //  Created by Erfan on 4/23/14.
  6. //
  7. //
  8.  
  9. #import <Foundation/Foundation.h>
  10. #include "NSsocket.h"
  11. #import "mach/mach.h"
  12. #include <sys/time.h>
  13. #include <netdb.h>
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include "PALcritsec.h"
  17. #include <list>
  18. #include <CoreFoundation/CFArray.h>
  19. #include "winEmul.h"
  20.  
  21. #include <openssl/ssl.h>
  22. #include <openssl/bio.h>
  23. #include <openssl/x509.h>
  24. #include <openssl/x509_vfy.h>
  25. #include <openssl/pem.h>
  26. #include <openssl/x509v3.h>
  27. #include <openssl/err.h>
  28. #include <openssl/conf.h>
  29. #include <fstream>
  30.  
  31. #define BUFFER_SIZE 4096
  32.  
  33. @interface NSsocket : NSObject <NSStreamDelegate> {
  34.     @private volatile bool m_bConnected;
  35.     @private volatile bool m_bHasSpaceAvailable;
  36.        
  37.     @private NSInputStream *m_pInputStream;
  38.     @private NSOutputStream *m_pOutputStream;
  39.        
  40.     @private HANDLE m_hSocketError;
  41.     @private HANDLE m_hSocketOpened;
  42.     @private HANDLE m_hSocketDataReceived;
  43.     @private HANDLE m_hSocketClosed;
  44.        
  45.     @private PAL::Mutex* m_pReadMutex;
  46.     @private PAL::Mutex* m_pWriteMutex;
  47.        
  48.     @private std::list<std::string> recvMessageBuffer;
  49.     @private std::list<std::string> sendMessageBuffer;
  50. }
  51.  
  52. -(NSStream *)GetStream:(bool)bInput;
  53. -(bool)CreateAndConnect:(const std::string&) serverAddress withPort:(const u_int16_t&) serverPort withTransportMode:(bool)bTLS;
  54. -(void)CloseConnection;
  55. -(void)CloseStreams;
  56. -(void)CloseEvents;
  57. -(bool)IsConnected;
  58. -(int)Send:(const std::string&)sDataToSend;
  59. -(int)Recv:(char *)dataReceived withBufferSize:(int)bufferSize;
  60. -(int)Select:(u_int64_t)uTimeoutValue;
  61. -(void)Signal;
  62.  
  63. @end
  64.  
  65. @implementation NSsocket
  66.  
  67. - (id)init
  68. {
  69.     self = [super init];
  70.     if(self)
  71.     {
  72.         // Must be created at the beginning, otherwise calling Select would cause a crash with NULL events
  73.         m_hSocketError = CreateEvent(NULL, FALSE, FALSE, NULL);
  74.         m_hSocketOpened = CreateEvent(NULL, FALSE, FALSE, NULL);
  75.         m_hSocketDataReceived = CreateEvent(NULL, FALSE, FALSE, NULL);
  76.         m_hSocketClosed = CreateEvent(NULL, FALSE, FALSE, NULL);
  77.        
  78.         m_pReadMutex = new PAL::Mutex;
  79.         m_pWriteMutex = new PAL::Mutex;
  80.     }
  81.    
  82.     return self;
  83. }
  84.  
  85. -(NSStream *)GetStream:(bool)bInput
  86. {
  87.     return bInput ? m_pInputStream : m_pOutputStream;
  88. }
  89.  
  90. SecTrustRef changeHostForTrust(SecTrustRef trust)
  91. {
  92.     CFMutableArrayRef newTrustPolicies = CFArrayCreateMutable(
  93.                                                               kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
  94.    
  95.     SecPolicyRef sslPolicy = SecPolicyCreateSSL(true, CFSTR("www.example.com"));
  96.    
  97.     CFArrayAppendValue(newTrustPolicies, sslPolicy);
  98.    
  99. #ifdef MAC_BACKWARDS_COMPATIBILITY
  100.     /* This technique works in OS X (v10.5 and later) */
  101.    
  102.     SecTrustSetPolicies(trust, newTrustPolicies);
  103.     CFRelease(oldTrustPolicies);
  104.    
  105.     return trust;
  106. #else
  107.     /* This technique works in iOS 2 and later, or
  108.      OS X v10.7 and later */
  109.    
  110.     CFMutableArrayRef certificates = CFArrayCreateMutable(
  111.                                                           kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
  112.    
  113.     /* Copy the certificates from the original trust object */
  114.     CFIndex count = SecTrustGetCertificateCount(trust);
  115.     CFIndex i=0;
  116.     for (i = 0; i < count; i++) {
  117.         SecCertificateRef item = SecTrustGetCertificateAtIndex(trust, i);
  118.         CFArrayAppendValue(certificates, item);
  119.     }
  120.    
  121.     /* Create a new trust object */
  122.     SecTrustRef newtrust = NULL;
  123.     if (SecTrustCreateWithCertificates(certificates, newTrustPolicies, &newtrust) != errSecSuccess) {
  124.         /* Probably a good spot to log something. */
  125.        
  126.         return NULL;
  127.     }
  128.    
  129.     return newtrust;
  130. #endif
  131. }
  132.  
  133. std::string gserverAddress;
  134. int gPort;
  135.  
  136. -(bool)CreateAndConnect:(const std::string&) serverAddress withPort:(const u_int16_t&) serverPort withTransportMode:(bool)bTLS
  137. {
  138.     gserverAddress = serverAddress;
  139.     gPort = serverPort;
  140.     NSLog(@"NSStream %p connecting to: %s:%d in %s", self, serverAddress.c_str(), serverPort, bTLS ? "TLS" : "TCP");
  141.    
  142.     CFStringRef remoteHost = CFStringCreateWithCString(kCFAllocatorDefault, serverAddress.c_str(), kCFStringEncodingMacRoman);
  143.    
  144.     CFReadStreamRef readStream;
  145.     CFWriteStreamRef writeStream;
  146.    
  147.     CFStreamCreatePairWithSocketToHost(NULL, remoteHost, serverPort, &readStream, &writeStream);
  148.    
  149.     // Set options then bridge to ARC:
  150.     if(bTLS)
  151.     {
  152.         NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
  153.                                   (id)kCFStreamSocketSecurityLevelTLSv1, kCFStreamPropertySocketSecurityLevel,
  154.                                   [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
  155.                                   [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
  156.                                   [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredRoots,
  157.                                   [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
  158.                                   nil];
  159.  
  160.         /*CFReadStreamSetProperty(readStream, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)settings);*/
  161.        
  162.        
  163.        
  164.        
  165.        
  166.        
  167.        
  168.         // Set this kCFStreamPropertySocketSecurityLevel before
  169.         // setting kCFStreamPropertySSLSettings.
  170.         // Setting kCFStreamPropertySocketSecurityLevel
  171.         // appears to override previous settings in kCFStreamPropertySSLSettings
  172.         CFReadStreamSetProperty(readStream,
  173.                                 kCFStreamPropertySocketSecurityLevel,
  174.                                 kCFStreamSocketSecurityLevelTLSv1);
  175.         // this disables certificate chain validation in ssl settings.
  176.         NSDictionary *sslSettings =
  177.         [NSDictionary dictionaryWithObjectsAndKeys:
  178.          (id)kCFBooleanFalse, (id)kCFStreamSSLValidatesCertificateChain,
  179.          nil];
  180.         CFReadStreamSetProperty(readStream,
  181.                                 kCFStreamPropertySSLSettings,
  182.                                 (__bridge CFDictionaryRef)sslSettings);
  183.        
  184.        
  185.        
  186.        
  187.        
  188.        
  189.        
  190.         CFWriteStreamSetProperty(writeStream, kCFStreamPropertySSLSettings, (__bridge CFDictionaryRef)settings);
  191.        
  192.         CFReadStreamOpen(readStream);
  193.         CFWriteStreamOpen(writeStream);
  194.     }
  195.    
  196.     CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  197.     CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
  198.  
  199.     m_pInputStream = (__bridge_transfer NSInputStream *)readStream;
  200.     m_pOutputStream = (__bridge_transfer NSOutputStream *)writeStream;
  201.    
  202.     [m_pInputStream setDelegate:self];
  203.     [m_pOutputStream setDelegate:self];
  204.    
  205.     recvMessageBuffer.clear();
  206.     sendMessageBuffer.clear();
  207.    
  208.     m_bConnected = false;
  209.     m_bHasSpaceAvailable = false;
  210.  
  211.     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
  212.     dispatch_async(queue, ^ {
  213.         // mainRunLoop used instead of currentRunLoop to avoid a crash on Logout
  214.         [m_pInputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
  215.         [m_pOutputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
  216.        
  217.         [m_pInputStream open];
  218.         [m_pOutputStream open];
  219.        
  220.         [[NSRunLoop currentRunLoop] run];
  221.     });
  222.    
  223.     return true;
  224. }
  225.  
  226. -(void)CloseConnection
  227. {
  228.     NSLog(@"NSStream %p closing connection", self);
  229.  
  230.     SetEvent(m_hSocketClosed);
  231.    
  232.     [self CloseStreams];
  233. }
  234.  
  235. -(void)CloseStreams
  236. {
  237.     m_bConnected = false;
  238.  
  239.     [m_pInputStream close];
  240.     [m_pOutputStream close];
  241.     [m_pInputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  242.     [m_pOutputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  243.    
  244.     recvMessageBuffer.clear();
  245.     sendMessageBuffer.clear();
  246. }
  247.  
  248. // Called as the destructor from the CNSsocket's destructor
  249. -(void)CloseEvents
  250. {
  251.     CloseEvent(m_hSocketError);
  252.     CloseEvent(m_hSocketOpened);
  253.     CloseEvent(m_hSocketDataReceived);
  254.     CloseEvent(m_hSocketClosed);
  255.    
  256.     delete m_pReadMutex;
  257.     delete m_pWriteMutex;
  258. }
  259.  
  260. -(bool)IsConnected
  261. {
  262.     return m_bConnected;
  263. }
  264.  
  265. -(int)Send:(const std::string&)sDataToSend
  266. {
  267.     PAL::Critical_Section cs(*m_pWriteMutex);
  268.     int iRet = sDataToSend.length();
  269.     if(m_bHasSpaceAvailable){
  270.         m_bHasSpaceAvailable = false;
  271.         //NSLog(@"NSStream %p sending data of length %lu", self, sDataToSend.length());
  272.         iRet = [m_pOutputStream write:(const uint8_t *)sDataToSend.c_str() maxLength:sDataToSend.length()];
  273.         //NSLog(@"NSStream %p sent length %d", self, iRet);
  274.     }
  275.     else{
  276.         sendMessageBuffer.push_back(sDataToSend);
  277.     }
  278.     return iRet;
  279. }
  280.  
  281. -(int)Recv:(char *)dataReceived withBufferSize:(int)bufferSize
  282. {
  283.     PAL::Critical_Section cs(*m_pReadMutex);
  284.     int dataLength = 0;
  285.     if (recvMessageBuffer.size() > 0)
  286.     {
  287.         std::string buffer = recvMessageBuffer.front();
  288.         recvMessageBuffer.pop_front();
  289.         dataLength = buffer.length() < bufferSize ? buffer.length() : bufferSize;
  290.         memcpy(dataReceived, buffer.c_str(), dataLength);
  291.         // TODO: if buffer.length is greater than bufferSize then the extra data should be stored back so that next time it returns this
  292.     }
  293.    
  294.     if(dataLength == 0 && [m_pInputStream streamStatus] >= NSStreamStatusClosed)
  295.     {
  296.         NSLog(@"NSStream %p recv error", self);
  297.         return -1;
  298.     }
  299.    
  300.     return dataLength;
  301.  
  302. }
  303.  
  304. -(int)Select:(u_int64_t)uTimeoutValue
  305. {
  306.     int iRet = 0;
  307.  
  308.     const int iNumEvents = 4;
  309.    
  310.     HANDLE EventArray[iNumEvents];
  311.     EventArray[0] = m_hSocketError;
  312.     EventArray[1] = m_hSocketOpened;
  313.     EventArray[2] = m_hSocketDataReceived;
  314.     EventArray[3] = m_hSocketClosed;
  315.  
  316.     DWORD dwWaitStatus = WaitForMultipleObjects(iNumEvents, EventArray, FALSE, uTimeoutValue);
  317.    
  318.     switch (dwWaitStatus)
  319.     {
  320.         case WAIT_FAILED:
  321.             break;
  322.            
  323.         case WAIT_OBJECT_0:
  324.             iRet = -1;
  325.             break;
  326.            
  327.         case WAIT_OBJECT_0 + 1:
  328.             iRet = 1;
  329.             break;
  330.            
  331.         case WAIT_OBJECT_0 + 2:
  332.             iRet = 1;
  333.             break;
  334.            
  335.         case WAIT_OBJECT_0 + 3:
  336.             iRet = 0;
  337.             break;
  338.            
  339.         default:
  340.             break;
  341.     }
  342.    
  343.     return iRet;
  344. }
  345.  
  346. -(void)Signal
  347. {
  348.     SetEvent(m_hSocketDataReceived);
  349. }
  350.  
  351.  
  352. static int openssl_verification(const char cert_filestr[], const char ca_bundlestr[]) {
  353.    
  354.     OpenSSL_add_all_algorithms();
  355.     ERR_load_BIO_strings();
  356.     ERR_load_crypto_strings();
  357.    
  358.     BIO *certbio = NULL;
  359.     BIO *cert2bio = NULL;
  360.     X509 *cert = NULL;
  361.     X509 *cert2 = NULL;
  362.     certbio = BIO_new(BIO_s_file());
  363.     int ret = BIO_read_filename(certbio, cert_filestr);
  364.     if(ret != 1) {
  365.         NSLog(@"Certificate Invalid.\n");
  366.     }
  367.     cert = PEM_read_bio_X509(certbio, NULL, 0, NULL);
  368.     BIO_free(certbio);
  369.    
  370.     cert2bio = BIO_new(BIO_s_file());
  371.     int ret2 = BIO_read_filename(certbio, cert_filestr);
  372.     if(ret2 != 1) {
  373.         NSLog(@"Certificate Invalid.\n");
  374.     }
  375.     cert2 = PEM_read_bio_X509(cert2bio, NULL, 0, NULL);
  376.     BIO_free(cert2bio);
  377.    
  378.     EVP_PKEY *pkey=X509_get_pubkey(cert2);
  379.     int result = X509_verify(cert, pkey);
  380.     EVP_PKEY_free(pkey);
  381.    
  382.     X509_free(cert);
  383.     X509_free(cert2);
  384.    
  385.     if(result > 0) {
  386.         NSLog(@"Certificate Verification Success.\n");
  387.     } else {
  388.         NSLog(@"Certificate Verification Failed.\n");
  389.     }
  390.    
  391.     return result > 0;
  392. }
  393.  
  394. #pragma mark NSStreamDelegate
  395.  
  396. - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
  397. {
  398.     NSLog(@"Kaidul Islam....\n");
  399.     NSLog(@"NSStream %p eventCode: %d", self, (int)eventCode);
  400.    
  401.     switch (eventCode) {
  402.         case NSStreamEventNone:
  403.             break;
  404.            
  405.         case NSStreamEventEndEncountered:
  406.             NSLog(@"NSStreamEventEndEncountered %@", [aStream streamError]);
  407.             [self CloseStreams];
  408.             SetEvent(m_hSocketError);
  409.             break;
  410.            
  411.         case NSStreamEventErrorOccurred:
  412.             NSLog(@"NSStreamEventErrorOccurred %@", [aStream streamError]);
  413.             [self CloseStreams];
  414.             SetEvent(m_hSocketError);
  415.             break;
  416.            
  417.         case NSStreamEventHasBytesAvailable:
  418.         {
  419.             if (aStream == m_pInputStream)
  420.             {
  421.                 PAL::Critical_Section cs(*m_pReadMutex);
  422.                 uint8_t buffer[BUFFER_SIZE];
  423.                 NSInteger bytesRead = [m_pInputStream read:buffer maxLength:BUFFER_SIZE];
  424.                
  425.                 if (0 >= bytesRead)
  426.                     break;
  427.                
  428.                 NSString *nsStringRead = [[NSString alloc] initWithBytes:buffer length:bytesRead encoding:NSUTF8StringEncoding];
  429.                
  430.                 std::string sStringRead = [nsStringRead UTF8String];
  431.                 recvMessageBuffer.push_back(sStringRead);
  432.                
  433.                 SetEvent(m_hSocketDataReceived);
  434.             }
  435.             break;
  436.         }
  437.         case NSStreamEventHasSpaceAvailable:
  438.         {
  439.             NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  440.             NSString *documentsDirectory = [paths objectAtIndex:0];
  441.             NSError *error2 = nil;
  442.            
  443.             NSString *certPath = [documentsDirectory stringByAppendingPathComponent:@"ss.der"];
  444.            
  445.             if (![[NSFileManager defaultManager] fileExistsAtPath:certPath])
  446.             {
  447.                 NSLog(@"File Doesn't exist");
  448.             }else {
  449.                 NSLog(@"Certificate Path %@\n",certPath);
  450.             }
  451.            
  452.             NSData * certData = nil;
  453.            
  454.             certData = [NSData dataWithContentsOfFile: certPath options: 1  error: &error2];
  455.             if (error2 || !certData) {
  456.                 NSLog(@"Read failed with error: %@", [error2 localizedDescription]);
  457.             }
  458.             else
  459.             {
  460.                 NSLog(@"Certificate Data: %@\n",certData);
  461.             }
  462.            
  463.             error2 = nil;
  464.             SecCertificateRef cert = (__bridge SecCertificateRef)[NSData dataWithContentsOfFile: certPath options: 1  error: &error2];
  465.            
  466.            
  467.             if(error2 || !cert)
  468.             {
  469.                 NSLog(@"Certificate Nil: %@",[error2 localizedDescription]);
  470.             }
  471.             else
  472.             {
  473.                 NSLog(@"Certificate is okay: %@", cert);
  474.             }
  475.            
  476.             ///////////////////////////////////////////1. Create Policy////////////////////////////////
  477.        
  478.             SecPolicyRef policy = SecPolicyCreateSSL(NO, CFSTR("https://www.smartbabymonitor.ugrow.philips.com"));
  479.             if(policy == NULL)
  480.             {
  481.                 NSLog(@"Policy is NULL");
  482.             }
  483.             else
  484.             {
  485.                 NSLog(@"Policy not NULL: %@", policy);
  486.             }
  487.            
  488.            
  489.             CFArrayRef streamCertificates = (CFArrayRef)CFBridgingRetain([aStream propertyForKey:(NSString *) kCFStreamPropertySSLPeerCertificates]);
  490.             if(streamCertificates == NULL)
  491.             {
  492.                 NSLog(@"NULL streamCertificates");
  493.             }
  494.             else
  495.             {
  496.                 NSLog(@"StreamCertificates is not NULL. Server CERTIFICATES: %@", streamCertificates);
  497.             }
  498.            
  499.            
  500.             //////////////////////////////////3. Create trust////////////////////////////////////////////
  501.            
  502.             SecTrustRef trust = NULL;
  503.             OSStatus status = SecTrustCreateWithCertificates(streamCertificates, policy, &trust);
  504.             if (status != noErr || trust == NULL) {
  505.                 NSLog(@"could not create a trust management object!");
  506.             }
  507.             else
  508.             {
  509.                 NSLog(@"StreamCertificates is created: %@", trust);
  510.                
  511.             }
  512.             NSLog(@"SecTrustCreateWithCertificates STATUS code :%d\n", (int)status); // 0 = errSecSuccess
  513.            
  514.            
  515.            
  516.             /////////////////////////////4. Set Anchor///////////////////////////////////////
  517.             CFArrayRef certArrayRef = CFArrayCreate(NULL, ( const void **)(&cert), (CFIndex) 1, NULL);
  518.             status = SecTrustSetAnchorCertificates(trust, certArrayRef);
  519.            
  520.             if (status != noErr || trust == NULL) {
  521.                 NSLog(@"could not SecTrustSetAnchorCertificates");
  522.             }
  523.             else
  524.             {
  525.                 // NSLog(@"SecTrustSetAnchorCertificates: %@", certArrayRef);
  526.                
  527.             }
  528.             // #5
  529.            
  530.             NSLog(@"SecTrustSetAnchorCertificates STATUS code :%d\n", (int)status);
  531.  
  532.            
  533.             /////////////////////////5. Verify Trust////////////////////////////////////
  534.            
  535.             SecTrustResultType trustResultType = kSecTrustResultUnspecified;
  536.            
  537.             // NSLog(@"trustResultType: %d", (int) trustResultType);
  538.            
  539.             status = SecTrustEvaluate(trust, &trustResultType); // issue
  540.            
  541.             // NSLog(@"status = %d, trustResultType = %d", (int) status, (int) trustResultType);
  542.            
  543.            
  544.             switch (trustResultType) {
  545.                 case kSecTrustResultProceed: // 1
  546.                     NSLog(@"kSecTrustResultProceed");
  547.                     break;
  548.                 case kSecTrustResultConfirm: // 2 - deprecated in iOS 7, but still valid in iOS 6
  549.                     NSLog(@"kSecTrustResultConfirm");
  550.                     break;
  551.                 case kSecTrustResultUnspecified: // 4
  552.                     NSLog(@"kSecTrustResultUnspecified");
  553.                     break;
  554.                 case kSecTrustResultRecoverableTrustFailure:  // 5
  555.                     NSLog(@"kSecTrustResultRecoverableTrustFailure");
  556.                     break;
  557.                 case kSecTrustResultDeny: // 3
  558.                     NSLog(@"kSecTrustResultDeny");
  559.                     break;
  560.                 case kSecTrustResultFatalTrustFailure: // 6
  561.                     NSLog(@"kSecTrustResultFatalTrustFailure");
  562.                     break;
  563.                 case kSecTrustResultOtherError: // 7
  564.                     NSLog(@"kSecTrustResultOtherError");
  565.                     break;
  566.                 case kSecTrustResultInvalid: // 0
  567.                     NSLog(@"kSecTrustResultInvalid");
  568.                     break;
  569.                 default:
  570.                     NSLog(@"default");
  571.                     break;
  572.             }
  573.            
  574.             if (status == errSecSuccess) {
  575.                 // expect trustResultType == kSecTrustResultUnspecified
  576.                 // until my cert exists in the keychain see technote for more detail.
  577.                 if (trustResultType == kSecTrustResultUnspecified) {
  578.                     NSLog(@"We can trust this certificate! TrustResultType: %d", trustResultType);
  579.                 } else {
  580.                     NSLog(@"Cannot trust certificate. TrustResultType: %d", trustResultType);
  581.                 }
  582.             } else {
  583.                 NSLog(@"Creating trust failed: %d", (int) status);
  584.                 [aStream close];
  585.             }
  586.            
  587.             NSLog(@".......................................................\n\n\n\n");
  588.             if (trust) {
  589.                 CFRelease(trust);
  590.                 NSLog(@"Trust Released.\n");
  591.             }
  592.             if (policy) {
  593.                 CFRelease(policy);
  594.                 NSLog(@"Policy Released.\n");
  595.             }
  596.  
  597.  
  598.            
  599.             if(aStream == m_pOutputStream)
  600.             {
  601.                 PAL::Critical_Section cs(*m_pWriteMutex);
  602.                 m_bHasSpaceAvailable = true;
  603.                 if(sendMessageBuffer.size() > 0)
  604.                 {
  605.                     std::string sDataToSend = sendMessageBuffer.front();
  606.                     sendMessageBuffer.pop_front();
  607.                     int iWritten = 0;
  608.                     if(sDataToSend.length() > 0)
  609.                     {
  610.                         m_bHasSpaceAvailable = false;
  611.                         iWritten = [m_pOutputStream write:(const uint8_t *)sDataToSend.c_str() maxLength:sDataToSend.length()];
  612.                     }
  613.                 }
  614.             }
  615.            
  616.             // SetEvent(m_hSocketOpened);
  617.         }
  618.         break;
  619.         case NSStreamEventOpenCompleted:
  620.             NSLog(@"NSStreamEventOpenCompleted");
  621.             m_bConnected = true;
  622.             //SetEvent(m_hSocketOpened);
  623.             break;
  624.            
  625.         default:
  626.             //NSLog(@"NSStream default");
  627.             break;
  628.     }
  629. }
  630.  
  631. @end
  632.  
  633. /**********************************************************
  634.  CNSsocket implementation
  635.  **********************************************************/
  636.  
  637.  
  638. CNSsocket::CNSsocket()
  639. {
  640.     m_pNSsocket = [[NSsocket alloc] init];
  641. }
  642.  
  643. CNSsocket::~CNSsocket()
  644. {
  645.     CloseConnection();
  646.     [m_pNSsocket CloseEvents];
  647. }
  648.  
  649. // [TODO] we MUST check the connection status
  650.  
  651. bool CNSsocket::CreateAndConnect(const std::string& serverAddress, const u_int16_t& serverPort, bool bTLS)
  652. {
  653.     return [m_pNSsocket CreateAndConnect:serverAddress withPort:serverPort withTransportMode:bTLS];
  654. }
  655.  
  656. void CNSsocket::GetLocalAddressAndPort(std::string& serverAddress, u_int16_t& serverPort)
  657. {
  658.     CFWriteStreamRef writeStream = (__bridge CFWriteStreamRef) [m_pNSsocket GetStream:false];
  659.    
  660.     // Get the native socket handle:
  661.     CFTypeRef socketTypeRef = CFWriteStreamCopyProperty(writeStream, kCFStreamPropertySocketNativeHandle);
  662.     if(socketTypeRef == NULL)
  663.     {
  664.         NSLog(@"Error in getting native socket handle");
  665.         serverAddress = "";
  666.         serverPort = 0;
  667.        
  668.         return;
  669.     }
  670.  
  671.     CFDataRef socketData = (CFDataRef)socketTypeRef;
  672.     CFSocketNativeHandle socket;
  673.     CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&socket);
  674.    
  675.     // Get the local socket address from the socket handle:
  676.     struct sockaddr_storage sa;
  677.     socklen_t salen = sizeof(sa);
  678.     getsockname(socket, (struct sockaddr *)&sa, &salen);
  679.    
  680.     // Get numeric host and port from socket address:
  681.     char host[NI_MAXHOST];
  682.     char service[NI_MAXSERV];
  683.     getnameinfo((struct sockaddr *)&sa, salen, host, sizeof(host), service, sizeof(service), NI_NUMERICHOST|NI_NUMERICSERV);
  684.    
  685.     serverAddress = std::string(host);
  686.     serverPort = (u_int16_t)atoi(service);
  687.    
  688.     NSLog(@"Local address: %s, local port: %d", serverAddress.c_str(), serverPort);
  689. }
  690.  
  691. void CNSsocket::CloseConnection()
  692. {
  693.     [m_pNSsocket CloseConnection];
  694. }
  695.  
  696. int CNSsocket::Send(const char* dataToSend, int sizeOfData)
  697. {
  698.     return [m_pNSsocket Send:std::string(dataToSend, sizeOfData)];
  699. }
  700.  
  701. int CNSsocket::Recv(char dataReceived[], int bufferSize)
  702. {
  703.     return [m_pNSsocket Recv:dataReceived withBufferSize:bufferSize];
  704. }
  705.  
  706.  
  707. // [TODO] We should use callback instead of select() to reduce processing cost.
  708. // This needs to be called after invoking CreateAndConnect to get connection status.
  709.  
  710. int CNSsocket::Select(u_int64_t timeOutValue)
  711. {
  712.     return [m_pNSsocket Select:timeOutValue];
  713. }
  714.  
  715. int CNSsocket::WaitForConnect(u_int64_t timeOutValue)
  716. {
  717.     u_int64_t slept = 0;
  718.     const u_int64_t duration = 50;
  719.     while(slept < timeOutValue){
  720.         if([m_pNSsocket IsConnected])
  721.             return 1;
  722.         usleep(duration * 1000);
  723.         slept += duration;
  724.     }
  725.     return [m_pNSsocket IsConnected] ? 1 : -1;
  726. }
  727.  
  728. void CNSsocket::Signal()
  729. {
  730.     [m_pNSsocket Signal];
  731. }
Advertisement
Add Comment
Please, Sign In to add comment