390 lines
9.9 KiB
Objective-C
390 lines
9.9 KiB
Objective-C
//
|
|
// ShakeManager.m
|
|
// Yoosee
|
|
//
|
|
// Created by guojunyi on 14-7-25.
|
|
// Copyright (c) 2014年 guojunyi. All rights reserved.
|
|
//
|
|
|
|
#import "ShakeManager.h"
|
|
#import "P2PClient.h"
|
|
#import "mesg.h"
|
|
#import "Constants.h"
|
|
#import "AppDelegate.h"
|
|
#import "Utils.h"
|
|
#import "UDManager.h"
|
|
|
|
#include <sys/types.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <arpa/inet.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <pthread.h>
|
|
#include <sys/_select.h>
|
|
|
|
@implementation ShakeManager
|
|
|
|
+ (id)sharedDefault
|
|
{
|
|
|
|
static ShakeManager *manager = nil;
|
|
@synchronized([self class]){
|
|
if(manager==nil){
|
|
DLog(@"Alloc ShakeManager");
|
|
manager = [[ShakeManager alloc] init];
|
|
manager.isSearching = NO;
|
|
manager.searchTime = 5;
|
|
}
|
|
}
|
|
return manager;
|
|
}
|
|
|
|
-(BOOL)search{
|
|
if(self.isSearching){
|
|
return NO;
|
|
}
|
|
|
|
GCDAsyncUdpSocket *socket = [[GCDAsyncUdpSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)];
|
|
NSError *error = nil;
|
|
if (![socket bindToPort:8899 error:&error])
|
|
{
|
|
//NSLog(@"Error binding: %@", [error localizedDescription]);
|
|
return NO;
|
|
}
|
|
if (![socket beginReceiving:&error])
|
|
{
|
|
//NSLog(@"Error receiving: %@", [error localizedDescription]);
|
|
return NO;
|
|
}
|
|
|
|
if (![socket enableBroadcast:YES error:&error])
|
|
{
|
|
//NSLog(@"Error enableBroadcast: %@", [error localizedDescription]);
|
|
return NO;
|
|
}
|
|
|
|
self.socket = socket;
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
int times = self.searchTime;
|
|
self.isSearching = YES;
|
|
while(times>0){
|
|
if ([[AppDelegate sharedDefault] isGoBack]) {
|
|
break;
|
|
}
|
|
[self sendUDPBroadcast];
|
|
usleep(1000000);
|
|
times --;
|
|
}
|
|
if(self.socket){
|
|
[self.socket close];
|
|
self.socket = nil;
|
|
}
|
|
self.isSearching = NO;
|
|
if(self.delegate){
|
|
[self.delegate onSearchEnd];
|
|
}
|
|
});
|
|
|
|
|
|
return YES;
|
|
}
|
|
|
|
- (void)sendUDPBroadcast
|
|
{
|
|
|
|
NSString *host = @"255.255.255.255";
|
|
int port = 8899;
|
|
|
|
sMesgShakeType message;
|
|
message.dwCmd = LAN_TRANS_SHAKE_GET;
|
|
message.dwStructSize = 28;
|
|
message.dwStrCon = 0;
|
|
|
|
Byte sendBuffer[1024];
|
|
memset(sendBuffer, 0, 1024);
|
|
sendBuffer[0] = 1;
|
|
|
|
NSData *myData = [NSData dataWithBytes:sendBuffer length:1024];
|
|
[self.socket sendData:myData toHost:host port:port withTimeout:-1 tag:0];
|
|
}
|
|
|
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didSendDataWithTag:(long)tag
|
|
{
|
|
// NSLog(@"did send");
|
|
}
|
|
|
|
- (void)udpSocketDidClose:(GCDAsyncUdpSocket *)sock withError:(NSError *)error
|
|
{
|
|
NSLog(@"error %@", error);
|
|
}
|
|
|
|
- (void)udpSocket:(GCDAsyncUdpSocket *)sock didReceiveData:(NSData *)data
|
|
fromAddress:(NSData *)address
|
|
withFilterContext:(id)filterContext
|
|
{
|
|
|
|
|
|
NSString *host = nil;
|
|
uint16_t port = 0;
|
|
|
|
|
|
|
|
if (data) {
|
|
Byte receiveBuffer[1024];
|
|
[data getBytes:receiveBuffer length:1024];
|
|
|
|
if(receiveBuffer[0]==2){
|
|
|
|
[GCDAsyncUdpSocket getHost:&host port:&port fromAddress:address];
|
|
DLog(@"%@",host);
|
|
int contactId = *(int*)(&receiveBuffer[16]);
|
|
int type = *(int*)(&receiveBuffer[20]);
|
|
int flag = *(int*)(&receiveBuffer[24]);
|
|
DLog(@"%i:%i:%i",contactId,type,flag);
|
|
if(self.delegate){
|
|
|
|
[self.delegate onReceiveLocalDevice:[NSString stringWithFormat:@"%i",contactId] type:type flag:flag address:host];
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
-(int32_t)createTcpSocket
|
|
{
|
|
int32_t sock = -1;
|
|
while (1)
|
|
{
|
|
//没有连接wifi,肯定不是ap模式
|
|
NSString* ssid = [Utils currentWifiSSID];
|
|
if (ssid == nil) {
|
|
NSLog(@"get ap mode info failed, no wifi");
|
|
break;
|
|
}
|
|
|
|
//create sock
|
|
sock = socket(AF_INET, SOCK_STREAM, 0);
|
|
if (-1 == sock)
|
|
{
|
|
NSLog(@"get ap mode info failed, create sock error");
|
|
break;
|
|
}
|
|
|
|
//设置sock为非阻塞模式
|
|
int iFlag = fcntl(sock, F_GETFL);
|
|
fcntl(sock, F_SETFL, iFlag | O_NONBLOCK);
|
|
|
|
//socket地址
|
|
struct sockaddr_in addrDst;
|
|
memset((char*)&addrDst, 0, sizeof(addrDst));
|
|
addrDst.sin_family = AF_INET;
|
|
addrDst.sin_addr.s_addr = inet_addr(ap_address);
|
|
addrDst.sin_port = htons(10086);
|
|
|
|
int ret = connect(sock, (struct sockaddr*)&addrDst, sizeof(addrDst));
|
|
if(ret != 0)
|
|
{
|
|
int err = errno;
|
|
if((EINPROGRESS != err) &&
|
|
(EWOULDBLOCK != err) &&
|
|
(EAGAIN != err) &&
|
|
(EALREADY != err) &&
|
|
(EISCONN != err))
|
|
{
|
|
NSLog(@"connect failed, err = %d", err);
|
|
break;
|
|
}
|
|
}
|
|
|
|
//这一段似乎实在判断connect是否连接成功
|
|
fd_set fdr, fdw;
|
|
FD_ZERO(&fdr);
|
|
FD_ZERO(&fdw);
|
|
FD_SET(sock, &fdr);
|
|
FD_SET(sock, &fdw);
|
|
struct timeval timeout;
|
|
timeout.tv_sec = 3;
|
|
timeout.tv_usec = 0;
|
|
|
|
int res = select(sock + 1, &fdr, &fdw, NULL, &timeout);
|
|
if(res < 0)
|
|
{
|
|
NSLog(@"Network error...");
|
|
break;
|
|
}
|
|
else if(res == 0)
|
|
{
|
|
NSLog(@"Connect server timeout1");
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
if (FD_ISSET(sock, &fdw) && !FD_ISSET(sock, &fdr)) {
|
|
NSLog(@"Connected, res = %d", res);
|
|
}
|
|
else if(FD_ISSET(sock, &fdw) && FD_ISSET(sock, &fdr))
|
|
{
|
|
int error = 0;
|
|
socklen_t len = sizeof(error);
|
|
if(getsockopt(sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
|
|
{
|
|
//获取SO_ERROR属性选项,当然getsockopt也有可能错误返回
|
|
NSLog(@"getsockopt SO_ERROR failed");
|
|
break;
|
|
}
|
|
if(error != 0)
|
|
{
|
|
//如果error不为0, 则表示链接到此没有建立完成
|
|
NSLog(@"error = %d", error);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//设置回阻塞模式
|
|
fcntl(sock, F_SETFL, iFlag);
|
|
|
|
//设置socket超时
|
|
struct timeval ti;
|
|
ti.tv_sec=2;
|
|
ti.tv_usec=0;
|
|
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &ti, sizeof(int));
|
|
setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&ti,sizeof(ti));
|
|
return sock;
|
|
}
|
|
if (sock != -1) {
|
|
close(sock);
|
|
sock = -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
-(int)ApModeGetID
|
|
{
|
|
int dw3cid = 0;
|
|
int32_t sock = -1;
|
|
while (1)
|
|
{
|
|
NSLog(@"start create sock");
|
|
sock = [self createTcpSocket];
|
|
if (sock == -1) {
|
|
NSLog(@"create sock failed");
|
|
break;
|
|
}
|
|
|
|
sTransCheckDeviceWifiModeCmdType stru;
|
|
memset(&stru, 0, sizeof(sTransCheckDeviceWifiModeCmdType));
|
|
stru.dwCmd = 0;
|
|
|
|
//send message
|
|
NSLog(@"start send");
|
|
ssize_t numBytes = send(sock, &stru, sizeof(stru), 0);
|
|
if (numBytes <= 0) {
|
|
NSLog(@"send failed, send %ld bytes, error = %d", numBytes, errno);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"send %ld bytes, sock = %d", numBytes, sock);
|
|
}
|
|
|
|
NSLog(@"start recv");
|
|
//recv message
|
|
char buffer[1024];
|
|
numBytes = recv(sock, buffer, 1024, 0);
|
|
if (numBytes <= 0) {
|
|
NSLog(@"recv failed, recv %ld bytes sock=%d", numBytes, sock);
|
|
}
|
|
else
|
|
{
|
|
if (numBytes == sizeof(sTransCheckDeviceWifiModeCmdType)) {
|
|
sTransCheckDeviceWifiModeCmdType* pStru = (sTransCheckDeviceWifiModeCmdType*)buffer;
|
|
if (pStru->dwCmd == 1 && pStru->dwErrNo == 1) {
|
|
dw3cid = pStru->dw3CID;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (sock != -1) {
|
|
close(sock);
|
|
sock = -1;
|
|
}
|
|
|
|
NSLog(@"dw3cid = %d", dw3cid);
|
|
if (dw3cid != 0)
|
|
{
|
|
[UDManager pushAPSupportDevByContactID:dw3cid];
|
|
}
|
|
return dw3cid;
|
|
}
|
|
|
|
-(BOOL)ApModeSetWifiPassword:(NSString*)password
|
|
{
|
|
BOOL ret = NO;
|
|
int32_t sock = -1;
|
|
while (1)
|
|
{
|
|
sock = [self createTcpSocket];
|
|
if (sock == -1) {
|
|
break;
|
|
}
|
|
|
|
sTcpSetWifiCmdType stru;
|
|
memset(&stru, 0, sizeof(sTcpSetWifiCmdType));
|
|
stru.dwCmd = 2;
|
|
stru.bSetWifiInfo = 1;
|
|
memcpy(stru.sWifiInfo.cPassword, [password UTF8String], [password length]);
|
|
|
|
//send message
|
|
ssize_t numBytes = send(sock, &stru, sizeof(stru), 0);
|
|
if (numBytes <= 0) {
|
|
NSLog(@"send failed, send %ld bytes, error = %d", numBytes, errno);
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"send %ld bytes, sock = %d", numBytes, sock);
|
|
}
|
|
|
|
//recv message
|
|
char buffer[1024];
|
|
numBytes = recv(sock, buffer, 1024, 0);
|
|
if (numBytes <= 0) {
|
|
NSLog(@"recv failed, recv %ld bytes sock=%d", numBytes, sock);
|
|
}
|
|
else
|
|
{
|
|
if (numBytes == sizeof(sTcpSetWifiCmdType)) {
|
|
sTcpSetWifiCmdType* pStru = (sTcpSetWifiCmdType*)buffer;
|
|
if (pStru->dwCmd == 3 && pStru->dwErrNo == 0) {
|
|
ret = YES;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (sock != -1) {
|
|
close(sock);
|
|
sock = -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
@end
|