I am receiving a successful connection to the server and i am in my callback function:
I am trying to get the name of the host and print that to my console:
if(theType == kCFSocketConnectCallBack){
NSLog(#"Connection is accepted");
CFSocketNativeHandle nativeSocket = CFSocketGetNative(theSocket);
uint8_t name[SOCK_MAXADDRLEN];
socklen_t namelen = sizeof(name);
NSData *peer = nil;
if (getpeername(nativeSocket, (struct sockaddr *)name, &namelen) == 0) {
peer = [NSData dataWithBytes:name length:namelen];
NSString *string = [[NSString alloc] initWithData:peer encoding:NSUTF8StringEncoding];
NSLog(#"IP adress of connected peer: %#", string);
}
When i run the application in the debug mode i can see the IP address value assigned to name , so it's successful in getting the name , each value is uint8_t..
The peer length is showing me 16;
My problem converting it to NSData then NSString...
output:
2010-01-31 13:57:58.671 IP adress of connected peer: (null)
My string is being output as NULL,
Any advise is appreciated, thanks....
getpeername() doesn't return the host name of the remote side; it returns the address:
$ man getpeername
...
DESCRIPTION
The getpeername() function returns the address of the peer connected to
the specified socket.
You want getnameinfo():
$ man getnameinfo
...
DESCRIPTION
The getnameinfo() function is used to convert a sockaddr structure to a
pair of host name and service strings. It is a replacement for and pro-
vides more flexibility than the gethostbyaddr(3) and getservbyport(3)
functions and is the converse of the getaddrinfo(3) function.
or gethostbyaddr():
$ man gethostbyaddr
...
DESCRIPTION
The getaddrinfo(3) and getnameinfo(3) functions are preferred over the
gethostbyname(), gethostbyname2(), and gethostbyaddr() functions.
The gethostbyname(), gethostbyname2() and gethostbyaddr() functions each
return a pointer to an object with the following structure describing an
internet host referenced by name or by address, respectively.
sockaddr is a struct, not just a typedef for a character array. You need to pass getpeername the address to an actual sockaddr struct, and then build the string from the sa_data field of that struct--and that's assuming that sa_data is actually a string for your address type, which the documentation doesn't suggest you can actually count on. As another answer says, this is not the call you want if your goal is to get a string representation to print out.
(Also, you don't need an NSData at all to go from a character array to an NSString; you can just use -[NSString initWithBytes:length:encoding:])
First, check to make sure that peer contains an instance of NSData that is non-zero in length.
If it does, then the most likely problem is that the data is not properly of the specified encoding causing NSString to fail the encoding and return a nil string. If it is an encoding issue, there is API on NSString for doing lossy encodings. Even if lossy isn't acceptable in your final solution, going that route can be quite helpful to figuring out what is going wrong.
That assumes by NULL you really mean nil. It would be helpful to paste the exact output of the log line.
Related
I am working Lightproperties(Color class) in CocoaFramework on mac os x. i want to create a bundle file from LightProperties.m, extconf.rb, LightProperties.h.
I receive this error:
error: bad receiver type 'float' redFloatValue = [redFloatValue
redComponent];
Thanks in Advance !
In your code fragment:
redFloatValue = [redFloatValue redComponent];
You are using the variable redFloatValue on the RHS in a position as the receiver of a message where a value of type NSColor * is (probably) required, and on the LHS where a variable of type CGFloat is (probably) required. A variable cannot be both these types, so one of the uses is wrong and the error message you show indicates it is the RHS one.
The (probably)'s above are because you've given so little information I can only guess what the types in your code actually are.
HTH
I want to send messages from a kernel extension into a userland program using kernel controls. I'm experiencing an EINVAL error when calling ctl_enqueuedata.
I've set up a Kernel Control and I'm trying to send messages through it using ctl_enqueuedata. I'm setting
ep_ctl.ctl_flags = 0
before passing to ctl_register, which, the documents suggest, should result in ctl_unit being automatically set.
To quote kern_control.h:
For a dynamically assigned control ID, do not set the CTL_FLAG_REG_ID_UNIT flag.
static struct kern_ctl_reg ep_ctl;
static kern_ctl_ref kctlref;
...
errno_t error;
bzero(&ep_ctl, sizeof(ep_ctl)); // sets ctl_unit to 0
ep_ctl.ctl_id = 0;
ep_ctl.ctl_unit = 0;
strncpy(ep_ctl.ctl_name, CONTROL_NAME, strlen(CONTROL_NAME));
ep_ctl.ctl_flags = 0x0; // not CTL_FLAG_REG_ID_UNIT so unit gets supplied. Not CTL_FLAG_PRIVILEGED either.
ep_ctl.ctl_send = EPHandleSend;
ep_ctl.ctl_getopt = EPHandleGet;
ep_ctl.ctl_setopt = EPHandleSet;
ep_ctl.ctl_connect = EPHandleConnect;
ep_ctl.ctl_disconnect = EPHandleDisconnect;
error = ctl_register(&ep_ctl, &kctlref);
printf("setupControl %d\n", error);
When I call ctl_register it returns 0 ok.
When I call ctl_enqueuedata, passing in my struct kern_ctl_reg I'm getting 22, which is EINVAL. One of those arguments appears to be incorrect. The other arguments I'm passing are a static test string and its length for data, and zero flags.
int result = ctl_enqueuedata(kctlref, ep_ctl.ctl_unit, filename, length, 0x0);
The value of my ep_ctl's .ctl_unit is 0, the value of .ctl_id is 6. Could it be that the ctl_unit value being passed to ctl_enqueuedata is invalid / un-initialized?
kern_control.h says of ctl_unit:
This field is ignored for a dynamically assigned control ID
Which suggests that it isn't required anyway?
Have I missed something in initializing my ep_ctl?
I believe you supply wrong value as the 2nd parameter of ctl_enqueuedata(). Instead of ep_ctl.ctl_unit, you have to remember struct sockaddr_ctl::sc_unit in the EPHandleConnect() callback and that's what you are supposed to pass into ctl_enqueuedata().
I suggest using OSX's kernel debugging facilities to figure out what's going on here. That will let you walk through the relevant kernel code, and should tell you where it's rejecting your input.
I have this code...
NSData* myData = producedData;
NSLog(#"Contents of myData: %#", myData);
The log prints
{
"id" = "";
"level" = "level_1";
"handle" = test;
}
How do I get the values for id and level and handle out of this? The original data is a NSString*.
Thanks!
Is it JSON? Use Stig Brautaset's JSON parser http://code.google.com/p/json-framework/
You aren't showing the code that actually obtains the data object, nor are you showing any code related to an NSString.
Are you just assigning a string (producedData) to your myData variable? That won't create a data object; for one thing, it wouldn't know what encoding to use to encode the string's characters into bytes, and more importantly, copying a pointer from one variable to another (which is what myData = producedData does—the variables do not contain the objects themselves, only pointers to them) does not change anything about what the pointer points to. The object will remain a string, even though you told the compiler that myData would point to a data object. The compiler should be warning you about this; you should heed and fix those warnings.
myData definitely is not a data object; if it were, its description of itself would be a hex dump. It is either a string or a dictionary.
The output you showed matches the syntax that an NSDictionary uses to describe itself. On the other hand, the object could be a string containing such a description. (This latter case is what you're expecting.)
If you have a dictionary: You're done! The object is already parsed.
If you have a string: Send it a propertyList message, which will parse the string as a property list and return whatever value is represented in it, which, in this case, will be a dictionary.
I'm sure that this has been asked MANY times before, but it's still giving me trouble. I define my class's Boolean property like this:
#property(readwrite,assign) BOOL namesVisible;
And it doesn't give compiler errors, but it NSLogs as (null). Obviously I'm doing something wrong here, but I'm at a loss to what it is.
BOOLs are just chars, either 0 or 1. As such, you don't need to use a storage keyword in the property declaration, so it should be:
#property (readwrite) BOOL namesVisible;
Second, when logging a BOOL, use the int format string, %d, or pass in a string:
NSLog(#"My Boolean: %d, or %#", object.namesVisible, object.namesVisible ? #"Yes" : #"No");
Because you're trying to log it as an object by using %#, and a BOOL isn't an object, and your property's value is NO and you're lucky.
The last part is because you're only passing a BOOL to NSLog, but since your format string says to expect an object pointer, it will read a pointer's worth from the argument stack. Since a pointer is bigger than a BOOL, it's reading more than you passed it. You're lucky that it got zeroes for all four/eight bytes (your NO was only one of them); the result is that it sent its description message to nil, which returned nil for the description string, which prints as “(null)” in the output.
If you'd been unlucky and/or the property's value had been YES, it would have read something that isn't nil, but is nonetheless probably not a pointer to an object that exists. As such, trying to log that would cause a crash, probably of the EXC_BAD_ACCESS variety. If you'd been unlucky and lucky at the same time, you would have printed the description of an actual object, and wondered how the hell your BOOL looked like that.
The solution is one of two things:
NSLog(#"My Boolean property: %d", (int)[myObject myBooleanProperty]);
or:
NSLog(#"My Boolean property: %#", [myObject myBooleanProperty] ? #"YES" : #"NO");
The former casts the Boolean value to a full-size int and prints that value as such (most probably either 0 or 1), whereas the latter will pass either #"YES" or #"NO" as the argument depending on the Boolean value. Since NSString literals are (NSString) objects, the %# formatter becomes the right one.
I have a threadMethod which shows in console robotMotorsStatus every 0.5 sec. But when I try to change robotMotorsStatus in changeRobotStatus method I receive an exception. Where I need to put the locks in that program.
#import "AppController.h"
#implementation AppController
extern char *robotMotorsStatus;
- (IBAction)runThread:(id)sender
{
[self performSelectorInBackground:#selector(threadMethod) withObject:nil];
}
- (void)threadMethod
{
char string_to_send[]="QFF001100\r"; //String prepared to the port sending (first inintialization)
string_to_send[7] = robotMotorsStatus[0];
string_to_send[8] = robotMotorsStatus[1];
while(1){
[theLock lock];
usleep(500000);
NSLog (#"Robot status %s", robotMotorsStatus);
[theLock unlock];
}
}
- (IBAction)changeRobotStatus:(id)sender
{
robotMotorsStatus[0]='1';
}
extern char *robotMotorsStatus;
You have not, in any code that you've shown, set this pointer to point anywhere. (Are you using an SDK for some robotics package that will initialize this variable for you? If so, can you show the configuration setting that tells it that this is the variable to initialize?)
string_to_send[7] = robotMotorsStatus[0];
string_to_send[8] = robotMotorsStatus[1];
If that robotMotorsStatus has not been initialized by an SDK or by code not shown, then these are accessing memory at a random address. It would not surprise me if this were crashing you, and if this were the “exception” you referred to but did not name.
robotMotorsStatus[0]='1';
Same potential problem here.
NSLog (#"Robot status %s", robotMotorsStatus);
This assumes that robotMotorsStatus contains at least one character, and that the last one is a zero byte (the null character)—i.e., that robotMotorsStatus points to a C string. As I've already noted, you have not shown that robotMotorsStatus points to anything definite, and even if it does point somewhere, you have not shown that the contents of that memory are a C string.
If there isn't a null character within the actual bounds of the array, then the array does not contain a C string, and attempting to read the whole C string, as passing the array to a %s formatter does, will cause a crash after you go past the end of the array. If the other two accesses of robotMotorsStatus are not your crash, this one may be.
The solution here is to not only have the pointer variable point somewhere you've intended, but to have a valid C string—including the null character—completely within that space.
Incidentally, these problems have nothing to do with threads.