metaproxy  1.21.0
Public Member Functions | Public Attributes | List of all members
metaproxy_1::filter::Z3950Client::Rep Class Reference
Collaboration diagram for metaproxy_1::filter::Z3950Client::Rep:
Collaboration graph

Public Member Functions

Z3950Client::Assocget_assoc (Package &package)
 
void send_and_receive (Package &package, yf::Z3950Client::Assoc *c)
 
void release_assoc (Package &package)
 

Public Attributes

int m_general_timeout_sec
 
int m_connect_timeout_sec
 
int m_init_timeout_sec
 
int m_max_sockets_timeout_sec
 
int m_max_sockets
 
bool m_force_close
 
bool m_client_ip
 
bool m_bind_host
 
std::string m_charset
 
std::string m_default_target
 
std::string m_force_target
 
boost::mutex m_mutex
 
boost::condition m_cond_session_ready
 
std::map< mp::Session, Z3950Client::Assoc * > m_clients
 

Detailed Description

Definition at line 86 of file filter_z3950_client.cpp.

Member Function Documentation

◆ get_assoc()

yf::Z3950Client::Assoc * mp::filter::Z3950Client::Rep::get_assoc ( Package &  package)

Definition at line 330 of file filter_z3950_client.cpp.

331 {
332  // only one thread messes with the clients list at a time
333  boost::mutex::scoped_lock lock(m_mutex);
334 
335  std::map<mp::Session,yf::Z3950Client::Assoc *>::iterator it;
336 
337  Z_GDU *gdu = package.request().get();
338 
339  int max_sockets = package.origin().get_max_sockets();
340  if (max_sockets == 0)
341  max_sockets = m_max_sockets;
342 
343  it = m_clients.find(package.session());
344  if (it != m_clients.end())
345  {
346  it->second->m_queue_len++;
347  while (true)
348  {
349 #if 0
350  // double init .. NOT working yet
351  if (gdu && gdu->which == Z_GDU_Z3950 &&
352  gdu->u.z3950->which == Z_APDU_initRequest)
353  {
354  yazpp_1::SocketManager *s = it->second->m_socket_manager;
355  delete it->second; // destroy Z_Assoc
356  delete s; // then manager
357  m_clients.erase(it);
358  break;
359  }
360 #endif
361  if (!it->second->m_in_use)
362  {
363  it->second->m_in_use = true;
364  return it->second;
365  }
366  m_cond_session_ready.wait(lock);
367  }
368  }
369  if (!gdu || gdu->which != Z_GDU_Z3950)
370  {
371  package.move();
372  return 0;
373  }
374  // new Z39.50 session ..
375  Z_APDU *apdu = gdu->u.z3950;
376  // check that it is init. If not, close
377  if (apdu->which != Z_APDU_initRequest)
378  {
379  mp::odr odr;
380 
381  package.response() = odr.create_close(apdu,
382  Z_Close_protocolError,
383  "First PDU was not an "
384  "Initialize Request");
385  package.session().close();
386  return 0;
387  }
388  std::string target = m_force_target;
389  if (!target.length())
390  {
391  target = m_default_target;
392  std::list<std::string> vhosts;
393  mp::util::remove_vhost_otherinfo(&apdu->u.initRequest->otherInfo,
394  vhosts);
395  size_t no_vhosts = vhosts.size();
396  if (no_vhosts == 1)
397  {
398  std::list<std::string>::const_iterator v_it = vhosts.begin();
399  target = *v_it;
400  }
401  else if (no_vhosts == 0)
402  {
403  if (!target.length())
404  {
405  // no default target. So we don't know where to connect
406  mp::odr odr;
407  package.response() = odr.create_initResponse(
408  apdu,
409  YAZ_BIB1_INIT_NEGOTIATION_OPTION_REQUIRED,
410  "z3950_client: No vhost given");
411 
412  package.session().close();
413  return 0;
414  }
415  }
416  else if (no_vhosts > 1)
417  {
418  mp::odr odr;
419  package.response() = odr.create_initResponse(
420  apdu,
421  YAZ_BIB1_COMBI_OF_SPECIFIED_DATABASES_UNSUPP,
422  "z3950_client: Can not cope with multiple vhosts");
423  package.session().close();
424  return 0;
425  }
426  }
427 
428  // see if we have reached max number of clients (max-sockets)
429  boost::xtime xt;
430  xtime_get(&xt,
431 #if BOOST_VERSION >= 105000
432  boost::TIME_UTC_
433 #else
434  boost::TIME_UTC
435 #endif
436  );
437  xt.sec += m_max_sockets_timeout_sec;
438  while (max_sockets)
439  {
440  int no_not_in_use = 0;
441  int number = 0;
442  it = m_clients.begin();
443  for (; it != m_clients.end(); it++)
444  {
445  yf::Z3950Client::Assoc *as = it->second;
446  if (!strcmp(as->m_host.c_str(), target.c_str()))
447  {
448  number++;
449  if (!as->m_in_use)
450  no_not_in_use++;
451  }
452  }
453  yaz_log(YLOG_LOG, "Found num=%d/max=%d/idle=%d connections for %s",
454  number, max_sockets, no_not_in_use, target.c_str());
455  if (number < max_sockets)
456  break;
457  if (no_not_in_use == 0) // all in use..
458  {
459  mp::odr odr;
460 
461  package.response() = odr.create_initResponse(
462  apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
463  "z3950_client: max sessions");
464  package.session().close();
465  return 0;
466  }
467  if (!m_cond_session_ready.timed_wait(lock, xt))
468  {
469  mp::odr odr;
470 
471  package.response() = odr.create_initResponse(
472  apdu, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
473  "z3950_client: max sessions");
474  package.session().close();
475  return 0;
476  }
477  }
478 
479  yazpp_1::SocketManager *sm = new yazpp_1::SocketManager;
480  yazpp_1::PDU_Assoc *pdu_as = new yazpp_1::PDU_Assoc(sm);
481  yf::Z3950Client::Assoc *as =
482  new yf::Z3950Client::Assoc(sm, pdu_as, target.c_str(),
487  m_clients[package.session()] = as;
488  return as;
489 }
std::map< mp::Session, Z3950Client::Assoc * > m_clients

◆ release_assoc()

void mp::filter::Z3950Client::Rep::release_assoc ( Package &  package)

Definition at line 628 of file filter_z3950_client.cpp.

629 {
630  boost::mutex::scoped_lock lock(m_mutex);
631  std::map<mp::Session,yf::Z3950Client::Assoc *>::iterator it;
632 
633  it = m_clients.find(package.session());
634  if (it != m_clients.end())
635  {
636  it->second->m_in_use = false;
637  it->second->m_queue_len--;
638 
639  if (package.session().is_closed())
640  {
641  // destroy hint (send_and_receive)
642  it->second->m_destroyed = true;
643  if (it->second->m_queue_len == 0)
644  {
645  yazpp_1::SocketManager *s = it->second->m_socket_manager;
646  delete it->second; // destroy Z_Assoc
647  delete s; // then manager
648  m_clients.erase(it);
649  }
650  }
651  m_cond_session_ready.notify_all();
652  }
653 }

◆ send_and_receive()

void mp::filter::Z3950Client::Rep::send_and_receive ( Package &  package,
yf::Z3950Client::Assoc *  c 
)

Definition at line 520 of file filter_z3950_client.cpp.

522 {
523  if (c->m_destroyed)
524  return;
525 
526  c->m_package = &package;
527 
528  if (package.session().is_closed() && c->m_connected && !c->m_has_closed
529  && m_force_close)
530  {
531  mp::odr odr;
532 
533  package.request() = odr.create_close(
534  0, Z_Close_finished, "z3950_client");
535  c->m_package = 0; // don't inspect response
536  }
537  Z_GDU *gdu = package.request().get();
538 
539  if (!gdu || gdu->which != Z_GDU_Z3950)
540  return;
541 
542  if (gdu->u.z3950->which == Z_APDU_close)
543  c->m_has_closed = true;
544 
545  Z_APDU *apdu = gdu->u.z3950;
546 
547  // prepare connect
548  c->m_time_elapsed = 0;
549  c->m_waiting = true;
550  if (!c->m_connected)
551  {
552  std::string host(c->m_host);
553 
554  if (m_bind_host)
555  {
556  std::string bind_host = package.origin().get_bind_address();
557  if (bind_host.length())
558  {
559  host.append(" ");
560  host.append(bind_host);
561  }
562  }
563  if (c->client(host.c_str()))
564  {
565  mp::odr odr;
566  package.response() =
567  odr.create_close(gdu->u.z3950, Z_Close_peerAbort, 0);
568  package.session().close();
569  return;
570  }
571  c->timeout(1); // so timeoutNotify gets called once per second
572 
573 
574  while (!c->m_destroyed && c->m_waiting
575  && c->m_socket_manager->processEvent() > 0)
576  ;
577  }
578  if (!c->m_connected)
579  {
580  return;
581  }
582  mp::odr odr;
583  if (m_client_ip)
584  {
585  std::string peer_name2 = package.origin().get_address();
586  if (apdu->which == Z_APDU_initRequest && peer_name2.length())
587  {
588  Z_OtherInformation **oi = &apdu->u.initRequest->otherInfo;
589  char *peer_name1 =
590  yaz_oi_get_string_oid(oi, yaz_oid_userinfo_client_ip, 1, 1);
591  std::string pcomb;
592  if (peer_name1)
593  {
594  pcomb.append(peer_name1);
595  pcomb.append(", ");
596  }
597  pcomb.append(peer_name2);
598  yaz_oi_set_string_oid(&apdu->u.initRequest->otherInfo,
599  odr, yaz_oid_userinfo_client_ip,
600  1, pcomb.c_str());
601  }
602  }
603  if (apdu->which == Z_APDU_initRequest && m_charset.length() > 0)
604  set_charset_proposal(odr, apdu->u.initRequest, m_charset.c_str());
605 
606  // prepare response
607  c->m_time_elapsed = 0;
608  c->m_waiting = true;
609 
610  // relay the package ..
611  int len;
612  c->send_GDU(gdu, &len);
613 
614  switch (gdu->u.z3950->which)
615  {
616  case Z_APDU_triggerResourceControlRequest:
617  // request only..
618  break;
619  default:
620  // for the rest: wait for a response PDU
621  while (!c->m_destroyed && c->m_waiting
622  && c->m_socket_manager->processEvent() > 0)
623  ;
624  break;
625  }
626 }
static void set_charset_proposal(ODR odr, Z_InitRequest *req, const char *charset)

References set_charset_proposal().

Here is the call graph for this function:

Member Data Documentation

◆ m_bind_host

bool metaproxy_1::filter::Z3950Client::Rep::m_bind_host

Definition at line 96 of file filter_z3950_client.cpp.

◆ m_charset

std::string metaproxy_1::filter::Z3950Client::Rep::m_charset

Definition at line 97 of file filter_z3950_client.cpp.

◆ m_client_ip

bool metaproxy_1::filter::Z3950Client::Rep::m_client_ip

Definition at line 95 of file filter_z3950_client.cpp.

◆ m_clients

std::map<mp::Session,Z3950Client::Assoc *> metaproxy_1::filter::Z3950Client::Rep::m_clients

Definition at line 102 of file filter_z3950_client.cpp.

◆ m_cond_session_ready

boost::condition metaproxy_1::filter::Z3950Client::Rep::m_cond_session_ready

Definition at line 101 of file filter_z3950_client.cpp.

◆ m_connect_timeout_sec

int metaproxy_1::filter::Z3950Client::Rep::m_connect_timeout_sec

Definition at line 90 of file filter_z3950_client.cpp.

◆ m_default_target

std::string metaproxy_1::filter::Z3950Client::Rep::m_default_target

Definition at line 98 of file filter_z3950_client.cpp.

◆ m_force_close

bool metaproxy_1::filter::Z3950Client::Rep::m_force_close

Definition at line 94 of file filter_z3950_client.cpp.

◆ m_force_target

std::string metaproxy_1::filter::Z3950Client::Rep::m_force_target

Definition at line 99 of file filter_z3950_client.cpp.

◆ m_general_timeout_sec

int metaproxy_1::filter::Z3950Client::Rep::m_general_timeout_sec

Definition at line 89 of file filter_z3950_client.cpp.

◆ m_init_timeout_sec

int metaproxy_1::filter::Z3950Client::Rep::m_init_timeout_sec

Definition at line 91 of file filter_z3950_client.cpp.

◆ m_max_sockets

int metaproxy_1::filter::Z3950Client::Rep::m_max_sockets

Definition at line 93 of file filter_z3950_client.cpp.

◆ m_max_sockets_timeout_sec

int metaproxy_1::filter::Z3950Client::Rep::m_max_sockets_timeout_sec

Definition at line 92 of file filter_z3950_client.cpp.

◆ m_mutex

boost::mutex metaproxy_1::filter::Z3950Client::Rep::m_mutex

Definition at line 100 of file filter_z3950_client.cpp.


The documentation for this class was generated from the following file: