19 #include <epicsGetopt.h> 33 #if defined(_WIN32) && !defined(_MINGW) 34 FILE *popen(
const char *command,
const char *mode) {
35 return _popen(command, mode);
37 int pclose(FILE *stream) {
38 return _pclose(stream);
50 static const char lookup[] = {
51 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
52 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' 56 string toHex(
int8* ba,
size_t len) {
59 for (
size_t i = 0;
i < len;
i++)
63 int upper = (b>>4)&0x0F;
84 return (std::size_t)(b<0 ? b+256 : b);
89 std::size_t size = readSize(buffer);
105 vector<osiSockAddr> addresses;
110 typedef map<string, ServerEntry> ServerMap;
111 static ServerMap serverMap;
142 if (command != (
int8)0x04)
145 size_t payloadSize = receiveBuffer.
getInt();
146 if (payloadSize < (12+4+16+2))
156 memset(&serverAddress, 0,
sizeof(serverAddress));
157 serverAddress.
ia.sin_family = AF_INET;
164 if (serverAddress.
ia.sin_addr.s_addr == INADDR_ANY)
165 serverAddress.
ia.sin_addr = responseFrom.
ia.sin_addr;
169 serverAddress.
ia.sin_port = htons(port);
171 string protocol = deserializeString(&receiveBuffer);
178 ServerMap::iterator iter = serverMap.find(guidString);
179 if (iter != serverMap.end())
182 vector<osiSockAddr>& vec = iter->second.addresses;
183 for (vector<osiSockAddr>::const_iterator ai = vec.begin();
194 vec.push_back(serverAddress);
202 ServerEntry serverEntry;
203 serverEntry.guid = guidString;
204 serverEntry.protocol = protocol;
205 serverEntry.addresses.push_back(serverAddress);
206 serverEntry.version = version;
208 serverMap[guidString] = serverEntry;
214 bool discoverServers(
double timeOut)
223 fprintf(
stderr,
"Failed to create a socket: %s\n", errStr);
233 string addressList = configuration->getPropertyAsString(
"EPICS_PVA_ADDR_LIST",
"");
234 bool autoAddressList = configuration->getPropertyAsBoolean(
"EPICS_PVA_AUTO_ADDR_LIST",
true);
235 int broadcastPort = configuration->getPropertyAsInteger(
"EPICS_PVA_BROADCAST_PORT",
PVA_BROADCAST_PORT);
242 fprintf(
stderr,
"Unable to populate interface list\n");
246 for(IfaceNodeVector::const_iterator it(ifaces.begin()), end(ifaces.end()); it!=end; ++it)
248 if(it->validBcast && it->bcast.sa.sa_family == AF_INET) {
250 bcast.
ia.sin_port = htons(broadcastPort);
251 broadcastAddresses.push_back(bcast);
257 if (!addressList.empty())
262 appendList = &broadcastAddresses;
268 broadcastAddresses = list;
272 for (
size_t i = 0;
i < broadcastAddresses.size();
i++)
279 int status = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (
char *)&optval,
sizeof(optval));
284 fprintf(
stderr,
"Error setting SO_BROADCAST: %s\n", errStr);
290 memset(&bindAddr, 0,
sizeof(bindAddr));
291 bindAddr.
ia.sin_family = AF_INET;
292 bindAddr.
ia.sin_port = htons(0);
293 bindAddr.
ia.sin_addr.s_addr = htonl(INADDR_ANY);
295 status = ::bind(socket, (sockaddr*)&(bindAddr.
sa),
sizeof(sockaddr));
300 fprintf(
stderr,
"Failed to bind: %s\n", errStr);
311 memset(&timeout, 0,
sizeof(
struct timeval));
313 timeout.tv_usec = 250000;
315 status = ::setsockopt (socket, SOL_SOCKET, SO_RCVTIMEO,
316 (
char*)&timeout,
sizeof(timeout));
321 fprintf(
stderr,
"Error setting SO_RCVTIMEO: %s\n", errStr);
328 status = ::getsockname(socket, &responseAddress.
sa, &sockLen);
332 fprintf(
stderr,
"Failed to get local socket address: %s.", errStr);
337 ByteBuffer sendBuffer(buffer,
sizeof(buffer)/
sizeof(
char));
343 sendBuffer.putInt(4+1+3+16+2+1+2);
345 sendBuffer.putInt(0);
346 sendBuffer.putByte((int8_t)0x81);
347 sendBuffer.putByte((int8_t)0);
348 sendBuffer.putShort((int16_t)0);
352 sendBuffer.putShort((int16_t)ntohs(responseAddress.
ia.sin_port));
354 sendBuffer.putByte((int8_t)0x00);
355 sendBuffer.putShort((int16_t)0);
358 for (
size_t i = 0; i < broadcastAddresses.size(); i++)
363 LOG(
logLevelDebug,
"UDP Tx (%zu) -> %s", sendBuffer.getPosition(), strBuffer);
366 status = ::sendto(socket, sendBuffer.getBuffer(), sendBuffer.getPosition(), 0,
367 &broadcastAddresses[
i].sa,
sizeof(sockaddr));
372 fprintf(
stderr,
"Send error: %s\n", errStr);
383 ByteBuffer receiveBuffer(rxbuff,
sizeof(rxbuff)/
sizeof(
char));
392 receiveBuffer.
clear();
395 int bytesRead = ::recvfrom(socket, (
char*)receiveBuffer.
getBuffer(),
397 (sockaddr*)&fromAddress, &addrStructSize);
407 receiveBuffer.
flip();
409 processSearchResponse(fromAddress, receiveBuffer);
420 socketError == EAGAIN ||
437 fprintf(
stderr,
"Socket recv error: %s\n", errStr);
447 for (
size_t i = 0; i < broadcastAddresses.size(); i++)
450 status = ::sendto(socket, sendBuffer.getBuffer(), sendBuffer.getPosition(), 0,
451 &broadcastAddresses[
i].sa,
sizeof(sockaddr));
456 fprintf(
stderr,
"Send error: %s\n", errStr);
480 #define DEFAULT_TIMEOUT 3.0 484 fprintf (
stderr,
"\nUsage: pvlist [options] [<server address or GUID starting with '0x'>]...\n\n" 486 " -h: Help: Print this message\n" 487 " -V: Print version and exit\n" 488 " -i Print server info (when server address list/GUID is given)\n" 489 " -w <sec>: Wait time, specifies timeout, default is %f second(s)\n" 490 " -q: Quiet mode, print only error messages\n" 491 " -d: Enable debug output\n" 497 "\tpvlist 10.5.1.205:10000\n" 498 "\tpvlist 0x83DE3C540000000000BF351F\n\n" 519 int main (
int argc,
char *argv[])
524 bool printInfo =
false;
533 while ((opt =
getopt(argc, argv,
":hVw:qdF:f:i")) != -1) {
540 fprintf(
stdout,
"pvAccess %u.%u.%u%s\n",
541 EPICS_PVA_MAJOR_VERSION,
542 EPICS_PVA_MINOR_VERSION,
543 EPICS_PVA_MAINTENANCE_VERSION,
544 (EPICS_PVA_DEVELOPMENT_FLAG)?
"-SNAPSHOT":
"");
545 fprintf(
stdout,
"pvData %u.%u.%u%s\n",
546 EPICS_PVD_MAJOR_VERSION,
547 EPICS_PVD_MINOR_VERSION,
548 EPICS_PVD_MAINTENANCE_VERSION,
549 (EPICS_PVD_DEVELOPMENT_FLAG)?
"-SNAPSHOT":
"");
550 fprintf(
stdout,
"Base %s\n", EPICS_VERSION_FULL);
556 fprintf(
stderr,
"'%s' is not a valid timeout value " 557 "- ignored. ('pvlist -h' for help.)\n",
optarg);
571 "Unrecognized option: '-%c'. ('pvlist -h' for help.)\n",
576 "Option '-%c' requires an argument. ('pvlist -h' for help.)\n",
587 bool noArgs = (
optind == argc);
589 bool byGUIDSearch =
false;
590 for (
int i =
optind; i < argc; i++)
592 string serverAddress = argv[
i];
595 if (serverAddress.length() == 26 &&
596 serverAddress[0] ==
'0' &&
597 serverAddress[1] ==
'x')
606 if (noArgs || byGUIDSearch)
607 discoverServers(timeOut);
612 for (ServerMap::const_iterator iter = serverMap.begin();
613 iter != serverMap.end();
616 const ServerEntry&
entry = iter->second;
618 cout <<
"GUID 0x" << entry.guid <<
" version " << (int)entry.version <<
": " 619 << entry.protocol <<
"@[ ";
621 size_t count = entry.addresses.size();
622 for (
size_t i = 0; i < count; i++)
628 cout <<
" ]" << endl;
633 for (
int i =
optind; i < argc; i++)
635 string serverAddress = argv[
i];
638 if (serverAddress.length() == 26 &&
639 serverAddress[0] ==
'0' &&
640 serverAddress[1] ==
'x')
642 bool resolved =
false;
643 for (ServerMap::const_iterator iter = serverMap.begin();
644 iter != serverMap.end();
647 const ServerEntry&
entry = iter->second;
649 if (strncmp(entry.guid.c_str(), &(serverAddress[2]), 24) == 0)
662 fprintf(
stderr,
"Failed to resolve GUID '%s'!\n", serverAddress.c_str());
669 ->setId(
"epics:nt/NTURI:1.0")
672 ->addNestedStructure(
"query")
675 ->createStructure());
677 PVStructure::shared_pointer args(
getPVDataCreate()->createPVStructure(argstype));
679 args->getSubFieldT<
PVString>(
"scheme")->
put(
"pva");
680 args->getSubFieldT<
PVString>(
"path")->
put(
"server");
681 args->getSubFieldT<
PVString>(
"query.op")->
put(printInfo ?
"info" :
"channels");
684 std::cerr<<
"Query to "<<serverAddress<<
"\n"<<args<<
"\n";
687 PVStructure::shared_pointer ret;
691 ChannelProvider::shared_pointer(),
695 std::cerr<<
"Execute\n";
696 ret = rpc.
request(args, timeOut,
true);
697 }
catch(std::exception& e) {
698 std::cerr<<
"Error: "<<e.what()<<
"\n";
703 PVStringArray::shared_pointer pvs(ret->getSubField<
PVStringArray>(
"value"));
709 std::ostream_iterator<std::string>(std::cout,
"\n"));
712 std::cout<<ret<<
"\n";
717 return allOK ? 0 : 1;
#define SOCK_ECONNREFUSED
LIBCOM_API void epicsStdCall epicsSocketDestroy(SOCKET s)
unsigned epicsStdCall sockAddrToDottedIP(const struct sockaddr *paddr, char *pBuf, unsigned bufSize)
int getopt(int nargc, char *const *nargv, const char *ostr)
std::tr1::shared_ptr< detail::SharedPut > put
EPICS_ALWAYS_INLINE int8 getByte()
const char * getBuffer() const
const epics::pvData::int8 PVA_MAGIC
const epics::pvData::int8 PVA_CLIENT_PROTOCOL_REVISION
#define SET_LOG_LEVEL(level)
int main(int argc, char *argv[])
std::tr1::shared_ptr< const Structure > StructureConstPtr
bucket * lookup(char *name)
std::size_t getPosition() const
#define epicsScanDouble(str, to)
PVStructure::shared_pointer createRequest(std::string const &request)
void copy(PVValueArray< T > &pvFrom, size_t fromOffset, size_t fromStride, PVValueArray< T > &pvTo, size_t toOffset, size_t toStride, size_t count)
Copy a subarray from one scalar array to another.
void epicsSocketConvertErrnoToString(char *pBuf, unsigned bufSize)
EPICS_ALWAYS_INLINE int32 getInt()
LIBCOM_API SOCKET epicsStdCall epicsSocketCreate(int domain, int type, int protocol)
PVString is special case, since it implements SerializableArray.
#define LOG(level, format,...)
void setPosition(std::size_t pos)
epics::pvData::PVStructure::shared_pointer request(epics::pvData::PVStructure::shared_pointer const &pvArgument, double timeout=RPCCLIENT_DEFAULT_TIMEOUT, bool lastRequest=false)
std::vector< osiSockAddr > InetAddrVector
template class for all extensions of PVArray.
void encodeAsIPv6Address(ByteBuffer *buffer, const osiSockAddr *address)
std::vector< ifaceNode > IfaceNodeVector
const epics::pvData::int32 PVA_BROADCAST_PORT
This class implements a Bytebuffer that is like the java.nio.ByteBuffer.
BSD and SRV5 Unix timestamp.
Extended replacement for the Posix exit and atexit routines.
EPICS_ALWAYS_INLINE int16 getShort()
std::size_t getRemaining() const
FORCE_INLINE const FieldCreatePtr & getFieldCreate()
bool decodeAsIPv6Address(ByteBuffer *buffer, osiSockAddr *address)
#define THROW_BASE_EXCEPTION(msg)
void getSocketAddressList(InetAddrVector &ret, const std::string &list, int defaultPort, const InetAddrVector *appendList)
void setEndianess(int byteOrder)
ConfigurationEnviron SystemConfigurationImpl
bool pvAccessIsLoggable(pvAccessLogLevel level)
int epicsStdCall sockAddrAreIdentical(const osiSockAddr *plhs, const osiSockAddr *prhs)
string inetAddressToString(const osiSockAddr &addr, bool displayPort, bool displayHex)
int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr)
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
#define EPICS_ENDIAN_LITTLE