Browse Source

tags/2021-05-28
jules 17 years ago
parent
commit
78f413bf50
1 changed files with 469 additions and 439 deletions
  1. +469
    -439
      build/macosx/platform_specific_code/juce_mac_Network.mm

+ 469
- 439
build/macosx/platform_specific_code/juce_mac_Network.mm View File

@@ -1,439 +1,469 @@
/*
==============================================================================
This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.
------------------------------------------------------------------------------
JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.
JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.
==============================================================================
*/
#include "juce_mac_NativeHeaders.h"
#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>
BEGIN_JUCE_NAMESPACE
#include "../../../src/juce_core/text/juce_String.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/basics/juce_Logger.h"
#include "../../../src/juce_core/threads/juce_ScopedLock.h"
#include "../../../src/juce_core/threads/juce_WaitableEvent.h"
#include "../../../src/juce_core/threads/juce_Thread.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"
//#include "juce_mac_HTTPStream.h"
//==============================================================================
static bool GetEthernetIterator (io_iterator_t* matchingServices) throw()
{
mach_port_t masterPort;
if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
{
CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass);
if (dict != 0)
{
CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
if (propDict != 0)
{
CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue);
CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict);
CFRelease (propDict);
}
}
return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS;
}
return false;
}
int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numResults = 0;
io_iterator_t it;
if (GetEthernetIterator (&it))
{
io_object_t i;
while ((i = IOIteratorNext (it)) != 0)
{
io_object_t controller;
if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS)
{
CFTypeRef data = IORegistryEntryCreateCFProperty (controller,
CFSTR (kIOMACAddress),
kCFAllocatorDefault,
0);
if (data != 0)
{
UInt8 addr [kIOEthernetAddressSize];
zeromem (addr, sizeof (addr));
CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr);
CFRelease (data);
int64 a = 0;
for (int i = 6; --i >= 0;)
a = (a << 8) | addr[i];
if (! littleEndian)
a = (int64) swapByteOrder ((uint64) a);
if (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}
IOObjectRelease (controller);
}
IOObjectRelease (i);
}
IOObjectRelease (it);
}
return numResults;
}
//==============================================================================
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
const AutoPool pool;
String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject.replace (T("\""), T("\\\""))
<< "\", content:\""
<< bodyText.replace (T("\""), T("\\\""))
<< "\" & return & return}\r\n"
"tell newMessage\r\n"
"set visible to true\r\n"
"set sender to \"sdfsdfsdfewf\"\r\n"
"make new to recipient at end of to recipients with properties {address:\""
<< targetEmailAddress
<< "\"}\r\n";
for (int i = 0; i < filesToAttach.size(); ++i)
{
script << "tell content\r\n"
"make new attachment with properties {file name:\""
<< filesToAttach[i].replace (T("\""), T("\\\""))
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}
script << "end tell\r\n"
"end tell\r\n";
NSAppleScript* s = [[NSAppleScript alloc]
initWithSource: [NSString stringWithUTF8String: (const char*) script.toUTF8()]];
NSDictionary* error = 0;
const bool ok = [s executeAndReturnError: &error] != nil;
[s release];
return ok;
}
//==============================================================================
END_JUCE_NAMESPACE
using namespace JUCE_NAMESPACE;
@interface JuceURLConnection : NSInputStream
{
NSURLConnection* connection;
NSMutableData* data;
NSThread* runLoopThread;
NSRunLoop* runLoop;
bool initialised, hasFailed, hasFinished;
int position;
NSLock* dataLock;
}
- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req;
- (void) dealloc;
- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response;
- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error;
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data;
- (void) connectionDidFinishLoading: (NSURLConnection*) connection;
- (BOOL) isOpen;
- (int) read: (char*) dest numBytes: (int) num;
- (int) readPosition;
- (void) runThread: (id) dummyParam;
@end
@implementation JuceURLConnection
- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req
{
[super init];
data = [[NSMutableData data] retain];
dataLock = [[NSLock alloc] init];
connection = 0;
initialised = false;
hasFailed = false;
hasFinished = false;
runLoopThread = [[NSThread alloc] initWithTarget: self
selector: @selector (runThread:)
object: req];
[runLoopThread start];
while (! [runLoopThread isExecuting])
Thread::sleep (1);
while ([runLoopThread isExecuting] && ! initialised)
Thread::sleep (1);
return self;
}
- (void) dealloc
{
[connection cancel];
[runLoopThread cancel];
while ([runLoopThread isExecuting])
[NSThread sleepForTimeInterval: 0.001];
[runLoopThread release];
[connection release];
[data release];
[dataLock release];
[super dealloc];
}
- (void) runThread: (id) request
{
AutoPool pool;
runLoop = [NSRunLoop currentRunLoop];
connection = [[NSURLConnection alloc] initWithRequest: request
delegate: self
startImmediately: YES];
if (connection == nil)
{
hasFailed = true;
return;
}
initialised = true;
while (! ([[NSThread currentThread] isCancelled] || hasFailed || hasFinished))
{
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
}
}
- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response
{
[dataLock lock];
[data setLength: 0];
[dataLock unlock];
}
- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error
{
NSLog ([error description]);
hasFailed = true;
}
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData
{
[dataLock lock];
[data appendData: newData];
[dataLock unlock];
}
- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
hasFinished = true;
}
- (BOOL) isOpen
{
return connection != 0 && ! hasFailed;
}
- (int) readPosition
{
return position;
}
- (int) read: (char*) dest numBytes: (int) numNeeded
{
int numDone = 0;
while (numNeeded > 0)
{
int available = jmin (numNeeded, [data length]);
if (available > 0)
{
[dataLock lock];
[data getBytes: dest length: available];
[data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0];
[dataLock unlock];
numDone += available;
numNeeded -= available;
dest += available;
}
else
{
if (hasFailed || hasFinished)
break;
Thread::sleep (1);
}
}
position += numDone;
return numDone;
}
@end
BEGIN_JUCE_NAMESPACE
bool juce_isOnLine()
{
return true;
}
void* juce_openInternetFile (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
AutoPool pool;
NSMutableURLRequest* req = [NSMutableURLRequest
requestWithURL: [NSURL URLWithString: juceStringToNS (url)]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)];
if (req == nil)
return 0;
[req setHTTPMethod: isPost ? @"POST" : @"GET"];
//[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
StringArray headerLines;
headerLines.addLines (headers);
headerLines.removeEmptyStrings (true);
for (int i = 0; i < headerLines.size(); ++i)
{
const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim());
const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim());
if (key.isNotEmpty() && value.isNotEmpty())
[req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)];
}
if (isPost && postData.getSize() > 0)
{
[req setHTTPBody: [NSData dataWithBytes: postData.getData()
length: postData.getSize()]];
}
JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req];
if ([s isOpen])
return s;
delete s;
return 0;
}
void juce_closeInternetFile (void* handle)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
AutoPool pool;
[s release];
}
}
int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
AutoPool pool;
return [s read: (char*) buffer numBytes: bytesToRead];
}
return 0;
}
int juce_seekInInternetFile (void* handle, int newPosition)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
return [s readPosition];
return 0;
}
END_JUCE_NAMESPACE
/*
==============================================================================

This file is part of the JUCE library - "Jules' Utility Class Extensions"
Copyright 2004-7 by Raw Material Software ltd.

------------------------------------------------------------------------------

JUCE can be redistributed and/or modified under the terms of the
GNU General Public License, as published by the Free Software Foundation;
either version 2 of the License, or (at your option) any later version.

JUCE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with JUCE; if not, visit www.gnu.org/licenses or write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
Boston, MA 02111-1307 USA

------------------------------------------------------------------------------

If you'd like to release a closed-source product which uses JUCE, commercial
licenses are also available: visit www.rawmaterialsoftware.com/juce for
more information.

==============================================================================
*/

#include "juce_mac_NativeHeaders.h"

#include <IOKit/IOKitLib.h>
#include <IOKit/network/IOEthernetInterface.h>
#include <IOKit/network/IONetworkInterface.h>
#include <IOKit/network/IOEthernetController.h>

BEGIN_JUCE_NAMESPACE

#include "../../../src/juce_core/text/juce_String.h"
#include "../../../src/juce_core/basics/juce_Time.h"
#include "../../../src/juce_core/basics/juce_SystemStats.h"
#include "../../../src/juce_core/basics/juce_Logger.h"
#include "../../../src/juce_core/threads/juce_ScopedLock.h"
#include "../../../src/juce_core/threads/juce_WaitableEvent.h"
#include "../../../src/juce_core/threads/juce_Thread.h"
#include "../../../src/juce_core/containers/juce_MemoryBlock.h"
#include "../../../src/juce_core/text/juce_StringArray.h"
#include "../../../src/juce_core/misc/juce_PlatformUtilities.h"
#include "../../../src/juce_core/io/network/juce_URL.h"

//#include "juce_mac_HTTPStream.h"

//==============================================================================
static bool GetEthernetIterator (io_iterator_t* matchingServices) throw()
{
mach_port_t masterPort;

if (IOMasterPort (MACH_PORT_NULL, &masterPort) == KERN_SUCCESS)
{
CFMutableDictionaryRef dict = IOServiceMatching (kIOEthernetInterfaceClass);

if (dict != 0)
{
CFMutableDictionaryRef propDict = CFDictionaryCreateMutable (kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);

if (propDict != 0)
{
CFDictionarySetValue (propDict, CFSTR (kIOPrimaryInterface), kCFBooleanTrue);

CFDictionarySetValue (dict, CFSTR (kIOPropertyMatchKey), propDict);
CFRelease (propDict);
}
}

return IOServiceGetMatchingServices (masterPort, dict, matchingServices) == KERN_SUCCESS;
}

return false;
}

int SystemStats::getMACAddresses (int64* addresses, int maxNum, const bool littleEndian) throw()
{
int numResults = 0;
io_iterator_t it;

if (GetEthernetIterator (&it))
{
io_object_t i;

while ((i = IOIteratorNext (it)) != 0)
{
io_object_t controller;

if (IORegistryEntryGetParentEntry (i, kIOServicePlane, &controller) == KERN_SUCCESS)
{
CFTypeRef data = IORegistryEntryCreateCFProperty (controller,
CFSTR (kIOMACAddress),
kCFAllocatorDefault,
0);
if (data != 0)
{
UInt8 addr [kIOEthernetAddressSize];
zeromem (addr, sizeof (addr));

CFDataGetBytes ((CFDataRef) data, CFRangeMake (0, sizeof (addr)), addr);
CFRelease (data);

int64 a = 0;
for (int i = 6; --i >= 0;)
a = (a << 8) | addr[i];

if (! littleEndian)
a = (int64) swapByteOrder ((uint64) a);

if (numResults < maxNum)
{
*addresses++ = a;
++numResults;
}
}

IOObjectRelease (controller);
}

IOObjectRelease (i);
}

IOObjectRelease (it);
}

return numResults;
}

//==============================================================================
bool PlatformUtilities::launchEmailWithAttachments (const String& targetEmailAddress,
const String& emailSubject,
const String& bodyText,
const StringArray& filesToAttach)
{
const AutoPool pool;

String script;
script << "tell application \"Mail\"\r\n"
"set newMessage to make new outgoing message with properties {subject:\""
<< emailSubject.replace (T("\""), T("\\\""))
<< "\", content:\""
<< bodyText.replace (T("\""), T("\\\""))
<< "\" & return & return}\r\n"
"tell newMessage\r\n"
"set visible to true\r\n"
"set sender to \"sdfsdfsdfewf\"\r\n"
"make new to recipient at end of to recipients with properties {address:\""
<< targetEmailAddress
<< "\"}\r\n";

for (int i = 0; i < filesToAttach.size(); ++i)
{
script << "tell content\r\n"
"make new attachment with properties {file name:\""
<< filesToAttach[i].replace (T("\""), T("\\\""))
<< "\"} at after the last paragraph\r\n"
"end tell\r\n";
}

script << "end tell\r\n"
"end tell\r\n";

NSAppleScript* s = [[NSAppleScript alloc]
initWithSource: [NSString stringWithUTF8String: (const char*) script.toUTF8()]];
NSDictionary* error = 0;
const bool ok = [s executeAndReturnError: &error] != nil;
[s release];

return ok;
}

//==============================================================================
END_JUCE_NAMESPACE

using namespace JUCE_NAMESPACE;

//==============================================================================
@interface JuceURLConnection : NSObject
{
NSURLRequest* request;
NSURLConnection* connection;
NSMutableData* data;
Thread* runLoopThread;
bool initialised, hasFailed, hasFinished;
int position;
NSLock* dataLock;
}

- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req withCallback: (URL::OpenStreamProgressCallback*) callback withContext: (void*) context;
- (void) dealloc;
- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response;
- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error;
- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data;
- (void) connectionDidFinishLoading: (NSURLConnection*) connection;

- (BOOL) isOpen;
- (int) read: (char*) dest numBytes: (int) num;
- (int) readPosition;
- (void) stop;
- (void) createConnection;

@end

class JuceURLConnectionMessageThread : public Thread
{
JuceURLConnection* owner;
public:
JuceURLConnectionMessageThread (JuceURLConnection* owner_)
: Thread (T("http connection")),
owner (owner_)
{
startThread();
}

~JuceURLConnectionMessageThread()
{
stopThread (5000);
}

void run()
{
AutoPool pool;
[owner createConnection];

while (! threadShouldExit())
{
AutoPool pool;
[[NSRunLoop currentRunLoop] runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.01]];
}
}
};

@implementation JuceURLConnection

- (JuceURLConnection*) initWithRequest: (NSURLRequest*) req
withCallback: (URL::OpenStreamProgressCallback*) callback
withContext: (void*) context;
{
[super init];
request = req;
[request retain];
data = [[NSMutableData data] retain];
dataLock = [[NSLock alloc] init];
connection = 0;
initialised = false;
hasFailed = false;
hasFinished = false;

runLoopThread = new JuceURLConnectionMessageThread (self);

while (runLoopThread->isThreadRunning() && ! initialised)
{
if (callback != 0)
callback (context, -1, [[request HTTPBody] length]);

Thread::sleep (1);
}

return self;
}

- (void) dealloc
{
[self stop];

delete runLoopThread;
[connection release];
[data release];
[dataLock release];
[request release];
[super dealloc];
}

- (void) createConnection
{
connection = [[NSURLConnection alloc] initWithRequest: request
delegate: self];

if (connection == nil)
runLoopThread->signalThreadShouldExit();
}

- (void) connection: (NSURLConnection*) connection didReceiveResponse: (NSURLResponse*) response
{
[dataLock lock];
[data setLength: 0];
[dataLock unlock];
initialised = true;
}

- (void) connection: (NSURLConnection*) connection didFailWithError: (NSError*) error
{
NSLog ([error description]);
hasFailed = true;
initialised = true;
runLoopThread->signalThreadShouldExit();
}

- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) newData
{
[dataLock lock];
[data appendData: newData];
[dataLock unlock];
initialised = true;
}

- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
hasFinished = true;
initialised = true;
runLoopThread->signalThreadShouldExit();
}

- (BOOL) isOpen
{
return connection != 0 && ! hasFailed;
}

- (int) readPosition
{
return position;
}

- (int) read: (char*) dest numBytes: (int) numNeeded
{
int numDone = 0;
while (numNeeded > 0)
{
int available = jmin (numNeeded, [data length]);

if (available > 0)
{
[dataLock lock];
[data getBytes: dest length: available];
[data replaceBytesInRange: NSMakeRange (0, available) withBytes: nil length: 0];
[dataLock unlock];
numDone += available;
numNeeded -= available;
dest += available;
}
else
{
if (hasFailed || hasFinished)
break;

Thread::sleep (1);
}
}

position += numDone;
return numDone;
}

- (void) stop
{
[connection cancel];
runLoopThread->stopThread (5000);
}

@end
BEGIN_JUCE_NAMESPACE


bool juce_isOnLine()
{
return true;
}

void* juce_openInternetFile (const String& url,
const String& headers,
const MemoryBlock& postData,
const bool isPost,
URL::OpenStreamProgressCallback* callback,
void* callbackContext,
int timeOutMs)
{
AutoPool pool;

NSMutableURLRequest* req = [NSMutableURLRequest
requestWithURL: [NSURL URLWithString: juceStringToNS (url)]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: timeOutMs <= 0 ? 60.0 : (timeOutMs / 1000.0)];

if (req == nil)
return 0;

[req setHTTPMethod: isPost ? @"POST" : @"GET"];
//[req setCachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData];

StringArray headerLines;
headerLines.addLines (headers);
headerLines.removeEmptyStrings (true);

for (int i = 0; i < headerLines.size(); ++i)
{
const String key (headerLines[i].upToFirstOccurrenceOf (T(":"), false, false).trim());
const String value (headerLines[i].fromFirstOccurrenceOf (T(":"), false, false).trim());

if (key.isNotEmpty() && value.isNotEmpty())
[req addValue: juceStringToNS (value) forHTTPHeaderField: juceStringToNS (key)];
}

if (isPost && postData.getSize() > 0)
{
[req setHTTPBody: [NSData dataWithBytes: postData.getData()
length: postData.getSize()]];
}

JuceURLConnection* const s = [[JuceURLConnection alloc] initWithRequest: req
withCallback: callback
withContext: callbackContext];

if ([s isOpen])
return s;

[s release];
return 0;
}

void juce_closeInternetFile (void* handle)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
AutoPool pool;
[s stop];
[s release];
}
}

int juce_readFromInternetFile (void* handle, void* buffer, int bytesToRead)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
{
AutoPool pool;
return [s read: (char*) buffer numBytes: bytesToRead];
}

return 0;
}

int juce_seekInInternetFile (void* handle, int newPosition)
{
JuceURLConnection* const s = (JuceURLConnection*) handle;
if (s != 0)
return [s readPosition];

return 0;
}


END_JUCE_NAMESPACE

Loading…
Cancel
Save