TweetFollow Us on Twitter

MacSockets
Volume Number:7
Issue Number:12
Column Tag:Com Workshop

Related Info: Device Manager

Library for UNIX-based Clients

By Frank Storbeck, The Netherlands

Introduction.

From the moment that Apple Computer, Inc. came with its UDP-TCP/IP driver for the Macintosh, there was suddenly an increased potential for use of client-server programs as developed in the UNIX-world. Alas, Apple came with its own calls for addressing their UDP-TCP/IP driver (“.IPP”). The calls are essentially the standard low level PBOpen, PBControl and PBClose calls from the DeviceManager. The software includes a file named “TCPPB.h”, in which one finds the definitions for the various DeviceManager calls for the .IPP-driver. However it would be easy if one could use the standard UNIX calls for socket-based communication instead. This gives you the opportunity to port the UNIX software to the Mac. So I started to write a small library with the .IPP equivalents for the client-functions close, connect, recv, recvfrom, recvmsg, send, sendto, sendmsg, shutdown, and socket. To use the Mac as a server, you also need the equivalents of the functions accept, bind, listen and select, but, as I only needed the client-software, I left them out of the project. There are also some other constraints. These will be addressed in the next paragraph. To use the MacTCP software you need a Mac-512E or better and the appropriate LocalTalk- or Ethernet-compatible hardware.

The MacTCP package is available as a single-user developer kit (APDA™ # M0230LL/D). It contains the MacTCP software, a programmers guide and an administrator guide. A licence is required to redistribute the software.

Sockets.

In the manual titled “Network Programming Guide” from SUN®-microsystems (part number 800-3850-10) you can find a good explanation of the in’s and out’s of “Socket-Based Interprocess Communication”. Here only a short summary will follow.

Normally some host sets up a particular service. A client that wants to communicate with this server has to know the address of the host and what is called the port-number of the service. For the standard UNIX-services these port-numbers are “well known” (here I quoted from the manual pages), but if you want to start to offer a new service there is a range of numbers from which you can choose. In the example given here for the use of the code I choose the value 31768 (in a UNIX-system these values for the port-numbers can be found in the file /etc/services).

A socket-pair is a “two way communication channel between two processes”. Each of these processes has a socket that can be used both for sending and receiving of data to and from the other process. The processes may reside on the same or different hosts, but they have to use the same address domains, the same communication method and the same protocol. As I had to use the software for a special project for communication on board of a research vessel, I allowed some more constraints to the software: only internet addressing mode (AF_INET), stream-sockets (SOCK_STREAM) and of course the TCP-IP protocol are supported.

Normally a server-program runs on a host for as long as possible (i.e. between start-up and shut-down). It then waits for the action of some client-program. The client tries to connect to the server, sends a message that it wants some service and then waits for the answer from the server. This can go on for as long as the service is needed. Then the connection is closed down and the server waits for the next client to be served. It is also possible that a server works for more than one client simultaneously. In this case it has a socket for each of the various clients to be served.

The client and server programs

This scheme shows up in the sample code for client.c and server.c that can be found in the listing. They are examples of how to use the calls to the functions for the socket-based communication. After the server has been activated, the client can be started, and it sends the following message to the server:

From: client

To: server

Mssg: Hello server!

Then the server replies with another message:

From: server

To: client

Mssg: Hello client!\n

The server has to be run on some SUN workstation (because of the call bcopy, replace it eventually with the ANSI-C call memcpy, but beware, the order of the parameters is different; also there is a function bzero to clear the memory locations over some range - if not present, deactivate it: the locations will be overwritten by the message anyhow!) The client has been compiled with THINK-C (4.0) compiler. The THINK-C project must also contain the ANSI, MacTraps and UNIX libraries.

The client-program can also be run on a SUN workstation. Just activate the SUN_C macro.

Of course you can change client and server as you like. You can maintain the connection until the client sends some bye-bye message, messages can be sent in chunks etc. etc. Do as you like.

Diagram 1: Sequence for communication between some server and one or more clients.

Some notes on the library

MacTCP provides the use of an asynchronous notification routine. This means that when some exception occurs, a user specified function can be activated. This is here implemented by the function SockNotify, which is hidden to the user. It calls the function DoAlert that draws an alert box on the screen displaying the appropriate massage for some time. The default showing time is 4 seconds, but can be changed with the function SetDialogShowTime. When the time is zero or negative, no DialogBox will be shown. The function DoAlert is also used by the function perror. In this case a stopIcon and an OK-button are added. The DialogBox shows the error message until the user clicks on the OK-button. As the function cannot be sure that a resource for the DialogBox and its DialogItemList is available, it is built up in memory. Note that to use it, you must initialize the DialogManager etc., otherwise your Mac behaves like the mother of all field-battles. All this can be switched off by deactivating the MAC_APPL macro. In this case the messages will be shown on stderr, using the console-library from THINK-C.

There are some extra routines added: close_MacSocket, exit_MacSocket, perror_MacSocket, and strerror_MacSocket,. They are used to prevent direct calls to their UNIX and ANSI-C equivalents close, exit, perror and strerror. In the file MacSocket.h there are macros that make sure that these calls will be diverted to their equivalents in the MacSocket library. e.g., if you call close, close_MacSocket first tries to close a socket-based connection. If the socket doesn’t exist, it calls the standard function close. This is a particular noteworthy example: you might have a file descriptor with number 5 and a socket with number 5. The only way to close the file with file-descriptor 5 while keeping the socket with number 5 in good shape is calling close directly:

/* 1 */

#undef close /* to dactivate a call to close_MacSocket */
close(5);
#define close close_MacSocket /* to reactivate it */

The program includes some files that are not provided here: “types.h”, “socket.h, “in.h”, “netdb.h” and “TCPPB.h”. The first four come from the SUNOS 4.1 operating system and are copyrighted by the Regents of the University of California I am not sure if I can redistribute them, so they are not included. But if you want to port software from a UNIX-platform to the Mac, you must have access to them anyhow. The file “TCPPB.h” is copyrighted by Apple Computer, Inc.

Last note: the program was written using SUNOS 4.0. Now we are using version 4.1. There they don’t speak about “address families” but about “address protocols”. Hence the macro AF_INET has been renamed to AP_INET, but AF_INET still works.

Listings server.c:
/***
 ***
 *** To send data between stream sockets (having communication 
 *** style SOCK_STREAM)
 *** Code based on an example taken from SUN® Network Program
 *** ming Guide,chapter 10, A Socket-Based Interprocess 
 *** Communications Tutorial,Revision A, of 27 March 1990, 
 *** Fig. 10-11, pp. 270-271.
 ***/
#include<sys/types.h>
#include<sys/socket.h>
#include<sys/time.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#define TRUE(1)
#define DATA“\nFrom: server\nTo:   client\nMssg: Hello client!\n”
#define Port(31768)

main()
{
 int    sock, length;
 struct sockaddr_in server;
 int    msgsock;
 char buf[1024];
 fd_set ready;
 struct timeval  to;

 /* Create socket. */
 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock < 0)
 {
 perror(“Server--> opening stream socket”);
 exit(1);
 }
 /* Name socket using wildcards. */
 server.sin_family = AF_INET;
 server.sin_addr.s_addr = INADDR_ANY;
 server.sin_port = Port;
 if (bind(sock, (struct sockadd *)&server, sizeof server) < 0)
 {
 perror(“Server--> getting socket name”);
 exit(1);
 }
 printf(“Server--> Socket port #%d\n”, ntohs(server.sin_port));

 /* Start accepting connections. */
 listen(sock, 5);
 do
 {
 FD_ZERO(&ready);
 FD_SET(sock, &ready);
 to.tv_sec = 5;
 if (select(sock + 1, &ready, (fd_set *)0, (fd_set *)0, &to) < 0)
 {
 perror(“Server--> select”);
 continue;
 }
 if (FD_ISSET(sock, &ready))
 {
 msgsock = accept(sock, (struct sockaddr *) 0, (int *) 0);
 if (msgsock == -1)
 {
 perror(“Server--> accept”);
 }
 else
 {
 bzero(buf, sizeof buf);
 if ((length = recv(msgsock, buf, 1024, 0)) < 0)
 {
 perror(“Server--> reading stream message”);
 }
 else
 {
 buf[length] = ‘\0’;
 printf(“Server-->%s\n”, buf);
 }
 if (send(msgsock, DATA, sizeof DATA, 0) < 0)
 {
 perror(“Server--> sending steam message”);
 }
 }
 close(msgsock);
 }
 else
 {
 /* Do something else. */
 }
 } while (TRUE);
 exit(0);
}
Listing:  socket.h
/***
 *** Copyright (c) 1990 Rijksinstituut voor Visserijonderzoek.
 *** All rights reserved.
 ***
 *** Redistribution and use in source and binary forms are 
 *** permitted provided that this notice is preserved and that 
 *** due credit is given to the Rijksinstituut voor Visserijonderzoek 
at IJmuiden.
 *** This software is provided “as is” without express or implied warranty.
 ***
 *** @(#)MacSocket.h 1.2 91/01/25
 ***/

#ifndef _MacSocket_H_
#define _MacSocket_H_

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unix.h>
#include<DeviceMgr.h>

#include“types.h”
#include“socket.h”
#include“in.h”
#include“netdb.h”
#include“TCPPB.h”

#ifdef  LAB_VIEW

/* to prevent the use of the malloc() call in a LabVIEW CIN */
#define SockElmnttheSockElmnt
#define SizeOf(x)x
#define malloc(x)&x

#else

#define SizeOf sizeof

#endif  LAB_VIEW

#ifndef NIL
#define NIL ((void*) 0L)
#endif  NIL
#ifndef InFrontOfAll
#define InFrontOfAll ((Ptr) -1L)
#endif  InFrontOfAll
#ifndef True
#define True(1)
#endif  True
#ifndef False
#define False    (0)
#endif  False
#define Abort    True
#define ReportIt False
#define Asynchronous True
#define SynchronousFalse
#define ConnectTimeout  (15)
#define SendTimeout(15)
#define RecvTimeout(15)
#define CloseTimeout (15)
#define SockBufSize(16384)
#define UserDataSize (128)

#define noTCPDriver(-1)
#define invalidArgument (2)
#define nonSOCK_STREAM  (13)
#define nonSocket(38)
#define nonAF_INET (43)
#define noBufSpace (55)
#define commandInProgress (1)

/* to force the application first to use the MacSocket versions */
#define perror   perror_MacSocket
#define exitexit_MacSocket
#define close    close_MacSocket
#define strerror strerror_MacSocket

/* Prototypes */
intaccept(int s, struct sockaddr *addr, int addrlen);
intbind(int s, struct sockaddr *name, int namelen);
intclose_MacSocket(int s);
intconnect(int s, struct sockaddr_in *name, int namelen);
void  exit_MacSocket(int status);
intlisten(int s, int backlog);
void  perror_MacSocket(char *s);
intrecv(int s, char *msg, int len, int flags);
intrecvfrom(int s, char *msg, int len, int flags, struct sockaddr_in 
*from,
 int *fromlen);
intrecvmsg(int s, struct msghdr *msg, int flags);
intsend(int s, char *msg, int len, int flags);
intsendto(int s, char *msg, int len, int flags, struct sockaddr_in *to,
 int tolen);
intsendmsg(int s, struct msghdr *msg, int flags);
intshutdown(int s, int how);
#ifdef  MAC_APPL
void  SetDialogShowTime(int sec);
#endif  MAC_APPL
intsocket(int domain, int type, int protocol);
char* strerror_MacSocket(int errnum);

#endif _MacSocket_H_
Listing:  client.c
/***
 ***
 *** To send data between stream sockets (having communication style
 *** SOCK_STREAM)
 *** Code based on an example taken from SUN® Network Programming Guide,
 *** chapter 10, A Socket-Based Interprocess Communications Tutorial,
 *** Revision A, of 27 March 1990, Fig. 10-9, pp. 266-267.
 ***
 ***/

#ifdef  SUN_C
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netdb.h>
#include<stdio.h>
#else SUN_C
/*
#define MAC_APPL
*/
#include<console.h>
#include“MacSocket.h”
#define bcopy(s1, s2, n)  memcpy((s2), (s1), (n))
#endif  SUN_C

#define Port(31768)
#define DATA“\nFrom: client\nTo:   server\nMssg: Hello server!\n”

main()
{
 int    sock, mssgSize;
 struct sockaddr_in server;
 union
 {
 long   address;
 unsigned char domain[4];
 } host;
 char buf[1024];
 
#ifdef  MAC_APPL
 /* prevent showing informative MacTCP/IP messages */
 SetDialogShowTime(0);
#endif  MAC_APPL
 
 /* Create socket. */
 sock = socket(AF_INET, SOCK_STREAM, 0);
 if (sock < 0)
 {
 perror(“opening stream socket”);
 exit(1);
 }
 /* Connect socket using address 192.6.1.30 and port# */
 server.sin_family = AF_INET;
 host.domain[0] = 192;
 host.domain[1] = 6;
 host.domain[2] = 1;
 host.domain[3] = 30;
 bcopy((char*)&host.address, (char*)&server.sin_addr, 4);
 server.sin_port = Port;

 if (connect(sock, (struct sockaddr_in *)&server, sizeof server) < 0)
 {
 perror(“connecting stream socket”);
 exit(1);
 }
 if (send(sock, DATA, sizeof DATA, 0) < 0)
 {
 perror(“writing on stream socket”);
 exit(1);
 }
 if ((mssgSize = recv(sock, buf, sizeof buf, 0)) < 0)
 {
 perror(“reading on stream socket”);
 exit(1);
 }
 buf[mssgSize] = ‘\0’;
 printf(“Client--> %s\n”, buf);
 close(sock);
 exit(0);
}
Listing:  MacSocket.c
/***
 *** Copyright (c) 1990 Rijksinstituut voor Visserijonderzoek, IJmuiden.
 *** All rights reserved.
 ***
 *** Redistribution and use in source and binary forms are permitted
 *** provided that this notice is preserved and that due credit is given
 *** to the Rijksinstituut voor Visserijonderzoek at IJmuiden.
 *** This software is provided “as is” without express or implied warranty.
 ***
 *** @(#)MacSocket.c 1.7 91/04/04
 ***/

/*
#define MAC_APPL
*/
#include“MacSocket.h”

#define Connected(0x01)

typedef struct SockElmnt
{
 int    number;
 struct SockElmnt*next;
 TCPiopbthePB;
 char   sockBuf[SockBufSize];
} SockElmnt, *SockElmntPtr, **SockElmntHdl;

#ifdef  MAC_APPL

#define LineLength (350)
#define AMargin  (13)
#define BMargin  (23)
#define IconSize (32)
#define DlogTop  (66)
#define DlogLeft (50)
#define ButtonHeight (22)
#define ButtonLength (59)

typedef struct AlertDitl
{
 unsigned short  nItems;
 Handle textHandle;
 Rect   textRect;
 unsigned char text;
 unsigned char textSize;
 char   textString[8];
 Handle buttonHandle;
 Rect   buttonRect;
 unsigned char button;
 unsigned char buttonSize;
 char   buttonString[2];
 Handle iconHandle;
 Rect   iconRect;
 unsigned char icon;
 unsigned char iconSize;
 unsigned short  iconId;
 Handle outlineHandle;
 Rect   outlineRect;
 unsigned char outline;
 unsigned char outlineSize;
} AlertDitl, *AlertDitlPtr, **AlertDitlHdl;

#endif  MAC_APPL

#ifdef  close
#undef  close
#endif  close

#ifdef  exit
#undef  exit
#ifdef  MAC_APPL
#define exit(s)  ExitToShell()
#endif  MAC_APPL
#endif  exit

#ifdef  perror
#undef  perror
#endif  perror

#ifdef  strerror
#undef  strerror
#endif  strerror

/**
 **
 ** local prototypes
 **
 **/
static  voidDoAlert(int alertId, char* s1, char* s2, char* s3, char* 
s4);
static  SockElmntPtr CreateSocketStruct(void);
static  SockElmntPtr FindSocketStruct(int);
static  int OpenTCPDriver(void);
static  pascal voidOutlineProc(DialogPtr thePtr, int theItem);
static  voidPollTCPDriver(TCPiopb *thePB);
static  int RemoveSocketStruct(int);
static  pascal voidSockNotify(StreamPtr tcpStream,
 unsigned short eventCode,
 Ptr userDataPtr,
 unsigned short terminReason,
 struct ICMPReport *icmpMsg);

/**
 **
 ** local variables
 **
 **/
static  int errno_MacSocket = noErr;
static  int ioRefNumTCP;
static  charmacSocketErrorMssg[128] = “no error!”;
static  int showTime = 4;
static  int sockNumber = 4;
static  SockElmntPtr theHeadPtr = NIL;
static  charTCPDriverName[] = “\p.IPP”;
static  chartheUserData[UserDataSize];
static  charTCPDriverNotOpened = True;

#ifdef  LAB_VIEW

static  SockElmnttheSockElmnt;

#endif  LAB_VIEW

/***
 ***
 *** Mac versions the standard Socket-based internet communication protocol:
 ***
 ***/

/**
 **
 ** Local functions
 **
 **/

/*
 *
 * CreateSocketStruct - creates a data structure for a particular socket 
into a
 * linked list
 *
 */
static  SockElmntPtr CreateSocketStruct()
{
 register SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = (SockElmntPtr)malloc(SizeOf(SockElmnt))) == NIL)
 {
 errno_MacSocket = noBufSpace;
 return (NIL);
 }
 theSockPtr->next = theHeadPtr;
 theHeadPtr = theSockPtr;
 theSockPtr->number = ++sockNumber;
 return (theSockPtr);
}

#ifdef  MAC_APPL
/*
 *
 * DoAlert - shows an alert message on the screen. When alertId is negative,
 * no icon and OK-button are displayed. The Alert message is then “showTime”
 * seconds visible.
 *
 */
static void DoAlert(int alertId, char* s1, char* s2, char* s3, char* 
s4)
{
 AlertDitlPtr  theAlertDitlPtr;
 AlertDitlHdl  theAlertDitlHdl;
 DialogRecord  dlogRecord;
 DialogPtrtheDlogPtr;
 Rect   theBounds;
 int    theItem;
 int    textHeight;
 int    nChars;
 FontInfo theFont;
 
 if ((alertId < 0) && (showTime <= 0))
 {
 return;
 }
 
 theAlertDitlHdl = (AlertDitlHdl)NewHandle(sizeof(AlertDitl));
 if (theAlertDitlHdl != NIL)
 {
 HLock(theAlertDitlHdl);
 theAlertDitlPtr = * theAlertDitlHdl;
 
 nChars = (int)((unsigned char)*s1) +
 (int)((unsigned char)*s2) +
 (int)((unsigned char)*s3) +
 (int)((unsigned char)*s4);
 
 GetFontInfo(&theFont);
 textHeight = ((nChars * theFont.widMax) / LineLength + 1) *
 (theFont.ascent + theFont.descent + theFont.leading);
 if ((textHeight < IconSize) && (alertId >= 0))
 {
 textHeight = IconSize;
 }
 
 theAlertDitlPtr->nItems = (alertId >= 0) ? 3 : 0;
 
 theAlertDitlPtr->textHandle = ((void*) 0L);
 theAlertDitlPtr->textRect.top = AMargin - 3;
 theAlertDitlPtr->textRect.left = BMargin - 3;
 if (alertId >= 0)
 {
 theAlertDitlPtr->textRect.left += IconSize + BMargin;
 }
 theAlertDitlPtr->textRect.bottom =
 theAlertDitlPtr->textRect.top + textHeight;
 theAlertDitlPtr->textRect.right =
 theAlertDitlPtr->textRect.left + LineLength;
 theAlertDitlPtr->text = statText + itemDisable;
 theAlertDitlPtr->textSize = 8;
 theAlertDitlPtr->textString[0] = ‘^’;
 theAlertDitlPtr->textString[1] = ‘0’;
 theAlertDitlPtr->textString[2] = ‘^’;
 theAlertDitlPtr->textString[3] = ‘1’;
 theAlertDitlPtr->textString[4] = ‘^’;
 theAlertDitlPtr->textString[5] = ‘2’;
 theAlertDitlPtr->textString[6] = ‘^’;
 theAlertDitlPtr->textString[7] = ‘3’;
 
 if (alertId >= 0)
 {
 theAlertDitlPtr->buttonHandle = ((void*) 0L);
 theAlertDitlPtr->buttonRect.top =
 theAlertDitlPtr->textRect.bottom + AMargin;
 theAlertDitlPtr->buttonRect.right =
 theAlertDitlPtr->textRect.right;
 theAlertDitlPtr->buttonRect.bottom =
 theAlertDitlPtr->buttonRect.top + ButtonHeight;
 theAlertDitlPtr->buttonRect.left =
 theAlertDitlPtr->buttonRect.right - ButtonLength;
 theAlertDitlPtr->button = ctrlItem + btnCtrl;
 theAlertDitlPtr->buttonSize = 2;
 theAlertDitlPtr->buttonString[0] = ‘O’;
 theAlertDitlPtr->buttonString[1] = ‘K’;
 
 theAlertDitlPtr->iconHandle = ((void*) 0L);
 theAlertDitlPtr->iconRect.top = theAlertDitlPtr->textRect.top;
 theAlertDitlPtr->iconRect.left = BMargin - 3;
 theAlertDitlPtr->iconRect.bottom =
 theAlertDitlPtr->iconRect.top + IconSize;
 theAlertDitlPtr->iconRect.right =
 theAlertDitlPtr->iconRect.left + IconSize;
 theAlertDitlPtr->icon = iconItem + itemDisable;
 theAlertDitlPtr->iconSize = 2;
 theAlertDitlPtr->iconId = alertId;
 
 theAlertDitlPtr->outlineHandle = (Handle)&OutlineProc;
 theAlertDitlPtr->outlineRect.top = theAlertDitlPtr->buttonRect.top;
 theAlertDitlPtr->outlineRect.left = theAlertDitlPtr->buttonRect.left;
 theAlertDitlPtr->outlineRect.bottom =
 theAlertDitlPtr->buttonRect.bottom;
 theAlertDitlPtr->outlineRect.right = theAlertDitlPtr->buttonRect.right;
 theAlertDitlPtr->outline = userItem + itemDisable;
 theAlertDitlPtr->outlineSize = 0;
 }
 
 theBounds.top = DlogTop;
 theBounds.left = DlogLeft;
 theBounds.bottom = DlogTop + AMargin - 3;
 theBounds.bottom += (alertId >= 0) ?
 theAlertDitlPtr->buttonRect.bottom :
 theAlertDitlPtr->textRect.bottom;
 theBounds.right = DlogLeft + theAlertDitlPtr->textRect.right + AMargin 
- 3;
 
 HUnlock(theAlertDitlHdl);
 
 ParamText(s1, s2, s3, s4);
 theDlogPtr = NewDialog(&dlogRecord, &theBounds, “\p”, True, dBoxProc,
 InFrontOfAll, False, 0L, theAlertDitlHdl);
 if (alertId >= 0)
 {
 ModalDialog(NIL, &theItem);
 }
 else
 {
 DrawDialog(theDlogPtr);
 sleep(showTime);
 }
 CloseDialog(theDlogPtr);
 DisposHandle(theAlertDitlHdl);
 }
};
#endif MAC_APPL

/*
 *
 * FindSocketStruct - finds a data structure for a particular socket 
in a linked list
 *
 */
static SockElmntPtrFindSocketStruct(int sock)
{
 register SockElmntPtr  theSockPtr;

 for (theSockPtr = theHeadPtr; theSockPtr != NIL;
   theSockPtr = (SockElmntPtr)theSockPtr->next)
 {
 if (theSockPtr->number == sock)
 {
 errno_MacSocket = noErr;
 return (theSockPtr);
 }
 }
 errno_MacSocket = nonSocket;
 return (NIL);
}

/*
 *
 * OpenTCPDriver - loads and opens UDP-TCP/IP driver (“.IPP”)
 *
 */
static  int OpenTCPDriver()
{
 ParamBlockRec thePB;
 
 thePB.ioParam.ioCompletion = NIL;
 thePB.ioParam.ioNamePtr = (StringPtr)TCPDriverName;
 thePB.ioParam.ioPermssn = fsCurPerm;
 PBOpen(&thePB, Asynchronous);
 PollTCPDriver((TCPiopb *)&thePB);
 if (errno_MacSocket == noErr)
 {
 TCPDriverNotOpened = False;
 ioRefNumTCP = thePB.ioParam.ioRefNum;
 return(1);
 }
 else
 {
 errno_MacSocket = noTCPDriver;
 return(0);
 }
}

#ifdef MAC_APPL
/*
 *
 * OutlineProc - Outlines an item in a dialogbox
 *
 */
static pascal void OutlineProc(WindowPtr thePtr, int theItem)
{
 int    theItemType;
 GrafPtrcurrentPort;
 Handle theItemHdl;
 Rect theBox;

 GetDItem (thePtr, theItem, &theItemType, &theItemHdl, &theBox);
 GetPort(&currentPort);
 SetPort(thePtr);
 PenSize(3, 3);
 InsetRect(&theBox, -4, -4);
 FrameRoundRect (&theBox, 16, 16);
 PenNormal();
 SetPort(currentPort);
};
#endif  MAC_APPL

/*
 *
 * PollTCPDriver - polls the UDP-TCP/IP driver until an action is completed
 *
 */
static  voidPollTCPDriver(TCPiopb *theTCPPtr)
{
 while((errno_MacSocket = theTCPPtr->ioResult) > 0)
 {
 SystemTask();
 }
}

/*
 *
 * RemoveSocketStruct - removes a data structure for a particular socket 
from a
 * linked list
 *
 */
static intRemoveSocketStruct(int sock)
{
 register SockElmntPtr  theSockPtr, thePrevOne = NIL;

 for (theSockPtr = theHeadPtr; theSockPtr != NIL;
   thePrevOne = theSockPtr, theSockPtr = (SockElmntPtr)theSockPtr->next)
 {
 if (theSockPtr->number == sock)
 {
 if (thePrevOne == NIL)
 {
 theHeadPtr = theSockPtr->next;
 }
 else
 {
 thePrevOne->next = theSockPtr->next;
 }
 free(theSockPtr);
 errno_MacSocket = noErr;
 return (1);
 }
 }
 errno_MacSocket = nonSocket;
 return(0);
}

/*
 *
 * SockNotify - prints notification messages for the UDP-TCP/IP driver
 *
 */
static pascal void SockNotify(StreamPtr tcpStream, unsigned short eventCode,
  Ptr userDataPtr, unsigned short terminReason, struct ICMPReport *icmpMsg)
{
 char theErrorMsg[128];
 char *errStrPtr1 = “\0”, *errStrPtr2 = “\0”;
#ifdef  MAC_APPL
 char errNoStr[32];
#endif  MAC_APPL
 
 strcpy(theErrorMsg, “MacSocket: “);
 switch (eventCode)
 {
 case TCPClosing:
 errStrPtr1 = “all data has been received and delivered”;
 break;
 case TCPULPTimeout:
 errStrPtr1 = “time out”;
 break;
 case TCPTerminate:
 errStrPtr1 = “connection terminated, “;
 switch(terminReason)
 {
 case TCPRemoteAbort:
 errStrPtr2 = “connection reset by peer”;
 break;
 case TCPNetworkFailure:
 errStrPtr2 = “network failure”;
 break;
 case TCPSecPrecMismatch:
 errStrPtr2 = “invallid security option or precedence level”;
 break;
 case TCPULPTimeoutTerminate:
 errStrPtr2 = “ULP time out”;
 break;
 case TCPULPAbort:
 errStrPtr2 = “connection aborted”;
 break;
 case TCPULPClose:
 errStrPtr2 = “connection closed gracefully”;
 break;
 case TCPServiceError:
 errStrPtr2 = “unexpected connection initiation segment read”;
 break;
 default:
 errStrPtr2 = “unknown reason”;
 break;
 }
 break;
 case TCPDataArrival:
 errStrPtr1 = “data arrived, no receive outstanding”;
 break;
 case TCPUrgent:
 errStrPtr1 = “urgent data arrived”;
 break;
 case TCPICMPReceived:
 errStrPtr1 = “Internet Control Message arrived”;
 /* still to be printed */
 break;
 default:
 errStrPtr1 = “unknown eventcode”;
 break;
 }
 strcat(theErrorMsg, errStrPtr1);
 strcat(theErrorMsg, errStrPtr2);
#ifndef MAC_APPL
 fprintf(stderr, “%s (%d).\n”, theErrorMsg, eventCode);
#else MAC_APPL
 NumToString(eventCode, errNoStr);
 DoAlert(-1, CtoPstr(theErrorMsg), “\p(“, errNoStr, “\p)”);
#endif  MAC_APPL
};

/**
 **
 ** Global functions
 **
 **/

/**
 **
 ** Functions that substitute relevant UNIX-system calls on the Mac
 **
 **/

/*
 *
 * close_MacSocket - delete a (socket) descriptor if present, else do 
close(int s)
 *
 */
int close_MacSocket(int s)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr, thePrevPtr = NIL;

 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return(close(s));
 }
 
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPClose;
 theTCPPtr->csParam.close.ulpTimeoutValue = CloseTimeout;
 theTCPPtr->csParam.close.ulpTimeoutAction = Abort;
 theTCPPtr->csParam.close.validityFlags = (byte)(timeoutValue | timeoutAction);
 theTCPPtr->csParam.close.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 theSockPtr->number = -1;
 if (errno_MacSocket == noErr)
 {
 return(0);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * exit_MacSocket - substitute for exit(int status)
 *
 */
void exit_MacSocket(int status)
{
 ParamBlockRec thePB;

 while (theHeadPtr != NIL)
 {
 shutdown(theHeadPtr->number, 2);
 }
 
 if (!TCPDriverNotOpened)
 {
 thePB.ioParam.ioCompletion = NIL;
 thePB.ioParam.ioRefNum = ioRefNumTCP;
 PBClose(&thePB, Asynchronous);
 /*
 PollTCPDriver(&thePB);
 */
 }
 exit(status);
}

/*
 *
 * perror_MacSocket - substitute for void perror(char *s)
 *
 */
void perror_MacSocket(char *s)
{
 char theErrorMsg[128];
#ifdef  MAC_APPL
 char errNoStr[32];
#endif  MAC_APPL
 
 strcpy(theErrorMsg, s);
 strcat(theErrorMsg, “: “);
 strcat(theErrorMsg, strerror_MacSocket(errno_MacSocket));
#ifndef MAC_APPL
 fprintf(stderr, “%s (%d).\n”, theErrorMsg, errno_MacSocket);
#else MAC_APPL
 NumToString(errno_MacSocket, errNoStr);
 DoAlert(stopIcon, CtoPstr(theErrorMsg), “\p (“, errNoStr, “\p).”);
#endif  MAC_APPL
}

/*
 *
 * strerror_MacSocket - substitute for strerror(int errnum)
 *
 */
char* strerror_MacSocket(int errnum)
{
 char *errStrPtr;
 
 switch (errnum)
 {
 case noTCPDriver:
 errStrPtr = “UDP-TCP/IP driver (\”.IPP\”) not available”;
 break;
 case invalidArgument:
 errStrPtr = “invalid address argument”;
 break;
 case nonSOCK_STREAM:
 errStrPtr = “socket type not supported”;
 break;
 case nonSocket:
 errStrPtr = “invalid socket descriptor”;
 break;
 case nonAF_INET:
 errStrPtr = “domain not supported”;
 break;
 case noBufSpace:
 errStrPtr = “no memory for buffers available”;
 break;
 case ipBadLapErr:
 errStrPtr = “bad network configuration”;
 break;
 case ipBadCnfgErr:
 errStrPtr = “bad IP configuration error”;
 break;
 case ipNoCnfgErr:
 errStrPtr = “missing IP or LAP configuration error”;
 break;
 case ipLoadErr:
 errStrPtr = “error in MacTCP load”;
 break;
 case ipBadAddr:
 errStrPtr = “error in getting address”;
 break;
 case streamAlreadyOpen:
 errStrPtr = “an open stream is already using this receive buffer area”;
 break;
 case invalidLength:
 errStrPtr = “the buffer is too small or too large”;
 break;
 case invalidBufPtr:
 errStrPtr = “illegal buffer pointer”;
 break;
 case insufficientResources:
 errStrPtr = “there are already 64 TCP streams open”;
 break;
 case invalidStreamPtr:
 errStrPtr = “the specified TCP stream is not open”;
 break;
 case connectionExists:
 errStrPtr = “this TCP stream has an open connection”;
 break;
 case duplicateSocket:
 errStrPtr = “a connection already exists on this link”;
 break;
 case commandTimeout:
 errStrPtr =
 “no connection attempt was received in the specified time-out period”;
 break;
 case openFailed:
 errStrPtr = “the connection came halfway up and then failed”;
 break;
 case connectionDoesntExist:
 errStrPtr = “there is no open connection on this stream”;
 break;
 case connectionClosing:
 errStrPtr = “a TCP close command was already issued”;
 break;
 case connectionTerminated:
 errStrPtr = “the connection went down”;
 break;
 case invalidRDS:
 errStrPtr = “trying to release wrong buffer”;
 break;
 default:
 errStrPtr = strerror(errnum);;
 break;
 }
 strcpy(macSocketErrorMssg, errStrPtr);
 return(macSocketErrorMssg);
}

/**
 **
 ** MacSocket calls
 **
 **/

/*
 *
 * connect - initiate a connection on a socket
 *
 */
int connect(int s, struct sockaddr_in *name, int namelen)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;
 
 if (namelen != sizeof(struct sockaddr_in))
 {
 errno_MacSocket = invalidArgument;
 return (-1);
 }

 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return (-1);
 }
 
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPActiveOpen;
 theTCPPtr->csParam.open.ulpTimeoutValue = ConnectTimeout;
 theTCPPtr->csParam.open.ulpTimeoutAction = Abort;
 theTCPPtr->csParam.open.validityFlags =
 (byte)(timeoutValue | timeoutAction | typeOfService | precedence);
 memcpy((void *)&theTCPPtr->csParam.open.remoteHost, (void *)&name->sin_addr,
 sizeof(name->sin_addr));
 theTCPPtr->csParam.open.remotePort = name->sin_port;
 theTCPPtr->csParam.open.localPort = 0;
 theTCPPtr->csParam.open.tosFlags = (byte)(reliability | lowDelay);
 theTCPPtr->csParam.open.precedence = 0;
 theTCPPtr->csParam.open.dontFrag = False;
 theTCPPtr->csParam.open.timeToLive = (byte)60;
 theTCPPtr->csParam.open.security = False;
 theTCPPtr->csParam.open.optionCnt = (byte)0;
 theTCPPtr->csParam.open.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return (0);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * recv - receive a message from a socket
 *
 */
int recv(int s, char *msg, int len, int flags)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return (-1);
 }
 
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPRcv;
 theTCPPtr->csParam.receive.commandTimeoutValue = RecvTimeout;
 theTCPPtr->csParam.receive.rcvBuff = msg;
 theTCPPtr->csParam.receive.rcvBuffLen = len;
 theTCPPtr->csParam.receive.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return (theTCPPtr->csParam.receive.rcvBuffLen);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * recvfrom - receive a message from a socket
 *
 */
int recvfrom(int s, char *msg, int len, int flags, struct sockaddr_in 
*from, int *fromlen)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (from != NULL)
 {
 *fromlen = sizeof(from);
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, from, *fromlen))
 {
 return(-1);
 }
 }
 }
 return(recv(s, msg, len, flags));
};

/*
 *
 * recvmsg - receive a message from a socket
 *
 */
int recvmsg(int s, struct msghdr *msg, int flags)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (msg->msg_name != NULL)
 {
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, (struct sockaddr_in *)msg->msg_name, msg->msg_namelen))
 {
 return(-1);
 }
 }
 }
 return(recv(s, (char *)msg->msg_iov, msg->msg_iovlen, flags));
};

/*
 *
 * send - send a message from a socket
 *
 */
int send(int s, char *msg, int len, int flags)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;

 struct theWDS
 {
 short  length;
 Ptr  theDataPtr;
 short  end;
 } theWDS;
 

 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return (-1);
 }
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPSend;
 theTCPPtr->csParam.send.ulpTimeoutValue = SendTimeout;
 theTCPPtr->csParam.send.ulpTimeoutAction = True;
 theTCPPtr->csParam.send.validityFlags = (byte)(timeoutValue | timeoutAction);
 theTCPPtr->csParam.send.pushFlag = True; /* May be false ?? */
 theTCPPtr->csParam.send.urgentFlag = False;
 theWDS.length = len;
 theWDS.theDataPtr = msg;
 theWDS.end = 0;
 theTCPPtr->csParam.send.wdsPtr = (Ptr)&theWDS;
 theTCPPtr->csParam.send.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return(len);
 }
 else
 {
 return (-1);
 }
};

/*
 *
 * sendto - send a message to a socket
 *
 */
int sendto(int s, char *msg, int len, int flags, struct sockaddr_in *to, 
int *tolen)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (to != NULL)
 {
 *tolen = sizeof(struct sockaddr_in);
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, to, *tolen))
 {
 return(-1);
 }
 }
 }
 return(send(s, msg, len, flags));
};

/*
 * sendmsg - send a message to a socket
 */
int sendmsg(int s, struct msghdr *msg, int flags)
{
 SockElmntPtr  theSockPtr;
 
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 errno_MacSocket = invalidStreamPtr;
 return (-1);
 }
 
 if (msg->msg_name != NULL)
 {
 if (!theSockPtr->state & Connected)
 {
 if (!connect(s, (struct sockaddr_in *)msg->msg_name, msg->msg_namelen))
 {
 return(-1);
 }
 }
 }
 return(send(s, (char *)msg->msg_iov, msg->msg_iovlen, flags));
};

#ifdef  MAC_APPL
/*
 *
 * SetDialogShowTime - sets the time that an MacTCP/IP info DialogBox 
is vissible.
 * when sec <= 0, no message will be displayed.
 *
 */
void SetDialogShowTime(int sec)
{
 showTime = sec;
}
#endif  MAC_APPL

/*
 *
 * shutdown - shut down part of a full-duplex connection
 *
 */
int shutdown(int s, int how)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;

 switch (how)
 {
 case 1: /* further sends disalowed */
 return (close_MacSocket(s));
 break;
 case 2: /* further sends and receives disalowed */
 if ((theSockPtr = FindSocketStruct(s)) == NIL)
 {
 return(-1);
 }
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->csCode = TCPRelease;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 return (RemoveSocketStruct(s));
 break;
 case 0: /* further receives disalowed */
 default:
 errno_MacSocket = invalidArgument;
 return(-1);
 break;
 }
};

/*
 * socket - create an endpoint for communication
 */
intsocket(int domain, int type, int protocol)
{
 TCPiopb*theTCPPtr;
 SockElmntPtr  theSockPtr;
 
 if (domain != AF_INET)
 {
 errno_MacSocket = nonAF_INET;
 return (-1);
 }
 if (protocol != 0)
 {
 errno_MacSocket = invalidArgument;
 return (-1);
 }
 if (type != SOCK_STREAM)
 {
 errno_MacSocket = nonSOCK_STREAM;
 return (-1);
 }
 if ((theSockPtr = (SockElmntPtr)CreateSocketStruct()) == NIL)
 {
 errno_MacSocket = noBufSpace;
 return (-1);
 }

 if (TCPDriverNotOpened)
 {
 if (!OpenTCPDriver())
 {
 return(-1);;
 }
 }
 theTCPPtr = &(theSockPtr->thePB);
 theTCPPtr->ioCompletion = NIL;
 theTCPPtr->ioRefNum = ioRefNumTCP;
 theTCPPtr->csCode = TCPCreate;
 theTCPPtr->csParam.create.rcvBuff = theSockPtr->sockBuf;
 theTCPPtr->csParam.create.rcvBuffLen = SockBufSize;
 theTCPPtr->csParam.create.notifyProc = SockNotify;
 theTCPPtr->csParam.create.userDataPtr = (Ptr)&theUserData;
 PBControl((ParmBlkPtr)theTCPPtr, Asynchronous);
 PollTCPDriver(theTCPPtr);
 if (errno_MacSocket == noErr)
 {
 return (theSockPtr->number);
 }
 else
 {
 RemoveSocketStruct(theSockPtr->number);
 return (-1);
 };
}
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

DesktopLyrics 2.6.6 - Displays current i...
DesktopLyrics is an application that displays the lyrics of the song currently playing in "iTunes" right on your desktop. The lyrics for the song have to be set in iTunes; DesktopLyrics does nothing... Read more
Ember 1.8.3 - Versatile digital scrapboo...
Ember (formerly LittleSnapper) is your digital scrapbook of things that inspire you: websites, photos, apps or other things. Just drag in images that you want to keep, organize them into relevant... Read more
Apple iTunes 12.1 - Manage your music, m...
Apple iTunes lets you organize and play digital music and video on your computer. It can automatically download new music, app, and book purchases across all your devices and computers. And it's a... Read more
LibreOffice 4.4.3 - Free, open-source of...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
FoldersSynchronizer 4.2.1 - Synchronize...
FoldersSynchronizer is a popular and useful utility that synchronizes and backs-up files, folders, disks and boot disks. On each session you can apply special options like Timers, Multiple Folders,... Read more
Simon 4.0.2 - Monitor changes and crashe...
Simon monitors websites and alerts you of crashes and changes. Select pages to monitor, choose your alert options, and customize your settings. Simon does the rest. Keep a watchful eye on your... Read more
Cocktail 8.1.2 - General maintenance and...
Cocktail is a general purpose utility for OS X that lets you clean, repair and optimize your Mac. It is a powerful digital toolset that helps hundreds of thousands of Mac users around the world get... Read more
Cyberduck 4.6.4 - FTP and SFTP browser....
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
Herald 5.0.2 - Notification plugin for M...
Note: Versions 2.1.3 (for OS X 10.7), 3.0.6 (for OS X 10.8), and 4.0.8 (for OS X 10.9) are no longer supported by the developer. Herald is a notification plugin for Mail.app, Apple's Mac OS X email... Read more
DEVONthink Pro 2.8.3 - Knowledge base, i...
Save 10% with our exclusive coupon code: MACUPDATE10 DEVONthink Pro is your essential assistant for today's world, where almost everything is digital. From shopping receipts to important research... Read more

Playworld Superheroes Review
Playworld Superheroes Review By Tre Lawrence on January 30th, 2015 Our Rating: :: HERO CRAFTINGUniversal App - Designed for iPhone and iPad It’s all about the imagination, fighting bad creatures — and looking good while doing so.   | Read more »
Join the SpongeBob Bubble Party in this...
Join the SpongeBob Bubble Party in this New Match 3 Bubble Poppin’ Frenzy Posted by Jessica Fisher on January 30th, 2015 [ permalink ] | Read more »
Handpick Review
Handpick Review By Jennifer Allen on January 30th, 2015 Our Rating: :: TANTALIZING SUGGESTIONSiPhone App - Designed for the iPhone, compatible with the iPad Handpick will make you hungry, as well as inspire you to cook something... | Read more »
Storm the Halls of Echo Base in First St...
Storm the Halls of Echo Base in First Star Wars: Galactic Defense Event Posted by Jessica Fisher on January 30th, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Contradiction Review
Contradiction Review By Tre Lawrence on January 30th, 2015 Our Rating: :: SPOT THE LIEiPad Only App - Designed for the iPad Contradiction is a live action point and click adventure that’s pretty engaging.   Developer: Tim Follin... | Read more »
Unlock Sunshine Girl in Ironkill with th...
Unlock Sunshine Girl in Ironkill with this special 148Apps code Posted by Rob Rich on January 29th, 2015 [ permalink ] Robo-fighter Ironkill has been out on iOS a | Read more »
Crossroad Zombies Review
Crossroad Zombies Review By Jordan Minor on January 29th, 2015 Our Rating: :: CROSSWALKING DEADiPad Only App - Designed for the iPad Crossroad Zombies is a rough draft of a cool genre mash-up.   | Read more »
Blood Brothers 2 – Tips, Cheats, and Str...
War is hell: Is it the kind of hell you want to check out? Read our Blood Brothers 2 review to find out! Blood Brothers 2, DeNA’s follow-up to the original Blood Brothers, is an intriguing card collecting / role-playing / strategy hybrid. There’s... | Read more »
Blood Brothers 2 Review
Blood Brothers 2 Review By Nadia Oxford on January 29th, 2015 Our Rating: :: AN AGGRAVATING RELATIVEUniversal App - Designed for iPhone and iPad Blood Brothers 2 is built on a simple, solid foundation, but its free-to-play system... | Read more »
I AM BREAD, the Toast of the Town, is Ro...
Have you ever dreamt of being deliciously gluten-y? Do you feel passionate about Rye and Wheat? The guys at Bossa Studios do and that is why they are bringing I AM BREAD to iOS soon. The loafy app will feature all the new content that is being... | Read more »

Price Scanner via MacPrices.net

Intel Aims to Transform Workplace With 5th-Ge...
Intel Corporation today announced the availability of its 5th generation Intel Core vPro processor family that provides cutting-edge features to enable a new and rapidly shifting workplace. To meet... Read more
iOS App Sharalike Introduces New Instant Smar...
Sharalike slideshow and photo management software for iOS, is making it easier than ever to create shareable meaningful moments with its new instant SmartShow technology. Staying organized is a goal... Read more
Apple Becomes World’s Largest Smartphone Vend...
According to the latest research data from Strategy Analytics, as global smartphone shipments grew 31 percent annually to reach a record 380 million units in the fourth quarter of 2014. Apple became... Read more
Cut the Cord: OtterBox Resurgence Power Case...
Dead batteries and broken phones are two of the biggest issues for smartphone users today. Otterbox addresses both with the new Resurgence Power Case for Apple iPhone 6, promising to make those panic... Read more
13-inch Retina MacBook Pros on sale for up to...
B&H Photo has 13″ Retina MacBook Pros on sale for $200 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.6GHz/128GB Retina MacBook Pro: $1199.99 save $100 - 13″ 2.6GHz/... Read more
15-inch 2.5GHz Retina MacBook Pro on sale for...
 B&H Photo has the 15″ 2.5GHz Retina MacBook Pro on sale for $2319.99 including free shipping plus NY sales tax only. Their price is $180 off MSRP, and it’s the lowest price available for this... Read more
Back in stock: Refurbished iPod nanos for $99...
The Apple Store has Apple Certified Refurbished 16GB iPod nanos available for $99 including free shipping and Apple’s standard one-year warranty. That’s $50 off the cost of new nanos. Most colors are... Read more
Apple lowers price on refurbished 256GB MacBo...
The Apple Store has lowered prices on Apple Certified Refurbished 2014 MacBook Airs with 256GB SSDs, now available for up to $200 off the cost of new models. An Apple one-year warranty is included... Read more
New Good Management Suite Simplifies Enterpri...
Good Technology has announced the availability of the Good Management Suite, a comprehensive cross-platform solution for organizations getting started with mobile business initiatives. Built on the... Read more
15-inch 2.0GHz Retina MacBook Pro (refurbishe...
The Apple Store has Apple Certified Refurbished previous-generation 15″ 2.0GHz Retina MacBook Pros available for $1489 including free shipping plus Apple’s standard one-year warranty. Their price is... Read more

Jobs Board

*Apple* Solutions Consultant- Retail Sales (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Event Director, *Apple* Retail Marketing -...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand Read more
At-Home Chat Specialist- *Apple* Online Stor...
**Job Summary** At Apple , we believe in hard work, a fun environment, and the kind of creativity and innovation that only comes about when talented people from diverse Read more
SW QA Engineer - *Apple* TV - Apple (United...
**Job Summary** The Apple TV team is looking for experienced Quality Assurance Engineers with a passion for delivering first in class home entertainment solutions. **Key Read more
*Apple* Retail - Multiple Positions(US) - Ap...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you re also the Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.